source: golgotha/src/golg/main.cc

Last change on this file was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 21.0 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "time/profile.hh"
10#include "window/wmanager.hh"
11#include "map.hh"
12#include "tile.hh"
13#include "app/app.hh"
14#include "controller.hh"
15#include "input.hh"
16#include "objs/map_piece.hh"
17#include "player.hh"
18#include "math/random.hh"
19#include "resources.hh"
20#include "menu.hh"
21#include "border_frame.hh"
22#include "sound/sfx_id.hh"
23#include "remove_man.hh"
24#include "saver.hh"
25#include "mess_id.hh"
26#include "sound_man.hh"
27#include "time/time.hh"
28#include "time/timedev.hh"
29#include "g1_speed.hh"
30#include "cwin_man.hh"
31#include "m_flow.hh"
32#include "g1_render.hh"
33#include "objs/defaults.hh"
34#include "net/startup.hh"       // g1 stuff for start network menus
35#include "network/net_prot.hh"  // so we can choose a protocol when we start
36#include "r1_api.hh"
37#include "g1_texture_id.hh"
38#include "statistics.hh"
39#include "map_man.hh"
40#include "tmanage.hh"
41#include "level_load.hh"
42#include "lisp/lisp.hh"
43#include "make_tlist.hh"
44#include "gui/image_win.hh"
45#include "font/anti_prop.hh"
46#include "lisp/li_init.hh"
47#include "objs/vehic_sounds.hh"
48#include "tick_count.hh"
49#include "map_view.hh"
50#include "demo.hh"
51#include "image_man.hh"
52
53#include <string.h>
54
55i4_profile_class pf_calc_model("calc model");
56i4_profile_class pf_calc_model_1("calc model 1");
57i4_profile_class pf_calc_model_2("calc model 2");
58i4_profile_class pf_calc_model_3("calc model 3");
59i4_profile_class pf_calc_model_4("calc model 4");
60i4_profile_class pf_calc_model_5("calc model 5");
61i4_profile_class pf_calc_model_6("calc model 6");
62i4_profile_class pf_calc_model_7("calc model 7");
63i4_profile_class pf_calc_model_8("calc model 8");
64i4_profile_class pf_calc_model_9("calc model 9");
65
66
67extern i4_grow_heap_class *g1_object_heap;
68
69int G1_HZ=10;
70
71static li_symbol_ref s_deterministic("deterministic");
72
73static char first_level[80];
74extern int last_draw_tick;
75extern int frame_locked_mode;
76
77class golgotha_app : public i4_application_class
78{
79private:
80  i4_window_class *main_menu;
81  i4_bool playing_movie;
82  w32 _max_memory;
83
84  w32 argc;
85  i4_const_str *argv;
86  i4_bool need_post_play_load;
87  i4_bool start_in_editor;
88
89  struct redraw_later_struct
90  {
91    i4_bool waiting;
92    i4_time_device_class::id id;
93
94    redraw_later_struct() { waiting=i4_F; }   
95  } redraw_later;
96
97
98  virtual w32 max_memory() { return _max_memory; }
99
100
101  i4_net_protocol *protocol;
102
103public: 
104
105  void handle_no_displays()
106  {
107#ifdef _WINDOWS
108    i4_error("Golgotha requires DirectX5, or a 3dfx card\n"
109             "Make sure you have DX5 (and are in 16bit color mode)"
110             "Or that you have the current version Glide (for 3dfx) installed");
111#else
112    i4_error("Golgotha requires a 3dfx card\n");
113#endif
114  }
115 
116  void pre_play_save();
117  void post_play_load();
118
119  golgotha_app(w32 argc, i4_const_str *argv)
120    : argc(argc), argv(argv)
121  {
122    start_in_editor=i4_F;
123    need_post_play_load=i4_F;
124    playing_movie=i4_F;
125    main_menu=0;
126    protocol=0;
127    _max_memory = 10*1024*1024;
128  }
129
130  void refresh()
131  {
132    g1_render.main_draw=i4_T;
133
134    if (g1_render.r_api)
135      g1_render.r_api->modify_features(R1_LOCK_CHEAT,g1_resources.lock_cheat);
136
137    i4_application_class::refresh();
138
139    g1_render.main_draw=i4_F;
140  }
141
142  void grab_time();
143
144
145
146  void map_changed()
147  {     
148    li_call("redraw");
149
150    if (redraw_later.waiting)
151      i4_time_dev.cancel_event(redraw_later.id);
152
153    redraw_later.waiting=i4_T;
154    i4_user_message_event_class m(G1_REDRAW_LATER);
155    redraw_later.id=i4_time_dev.request_event(this, &m, 500);
156  }
157
158  void init();
159 
160  virtual i4_bool idle() { return i4_F; }
161
162  void calc_model()
163  {
164    int fixed=li_get_value(s_deterministic.get())==li_true_sym;
165
166    if (g1_map_is_loaded())
167    {
168      pf_calc_model.start();
169
170      g1_render.r_api->get_tmanager()->next_frame();
171
172
173
174     
175
176
177      i4_time_class now;
178      sw32 md;
179      int ticks_simulated=0;
180      do
181      {
182        md=now.milli_diff(g1_get_map()->tick_time);
183        if (fixed || md>0 || frame_locked_mode)
184        {
185          if (!g1_resources.paused)
186          {
187            pf_calc_model_1.start();
188            g1_player_man.think();  // thinks player/team type thoughts
189            pf_calc_model_1.stop();
190
191            g1_map_class *map=g1_get_map();
192            map->think_objects();
193
194            g1_demo_tick();
195
196            if ((g1_tick_counter&7)==0)
197              g1_radar_update();
198
199
200            g1_remove_man.process_requests();
201            ticks_simulated++;
202          }
203          else
204            g1_get_map()->tick_time.add_milli((1000/G1_HZ));
205
206          if (g1_current_controller.get())
207            g1_current_controller->update_camera();
208         
209        }       
210      } while (!frame_locked_mode && !fixed && md>0 && ticks_simulated<10);
211     
212      if (ticks_simulated>=10) // simulation can't catch up with display
213        g1_get_map()->tick_time.get();      // catch up the time
214
215      if (g1_current_controller.get() &&
216          g1_current_controller->view.get_view_mode()!=G1_EDIT_MODE)
217        g1_current_controller->request_redraw(i4_F);
218
219
220      g1_sound_man.poll(i4_T);             // update sound effects (play next narative sfx)
221
222
223
224     
225      if (playing_movie)
226      {
227        if (!g1_get_map()->advance_movie_with_time())
228        {
229          playing_movie=i4_F;
230
231         
232          if (need_post_play_load)
233          {
234            if (g1_resources.paused)
235              li_call("Pause");
236            post_play_load();
237          }
238          else if (g1_current_controller.get())
239            g1_current_controller->view.suggest_camera_mode(G1_ACTION_MODE);
240        }
241
242        li_call("redraw");
243      }
244      else
245        g1_input.reset_esc();
246
247      pf_calc_model.stop();
248    }
249
250    g1_input.acknowledge();          // acknowledge that the keys have been examined   
251  }
252
253  void return_to_game();
254  void start_new_game();
255  void network_menu();
256  void server_menu();
257  void help_screen(char *screen_name, int next_id);
258  void plot_screen();
259  void client_wait_menu();
260  void do_main_menu();
261  void do_options();
262
263  void receive_event(i4_event *ev);
264  void uninit()
265  {
266    i4_kernel.unrequest_events(this,
267                               i4_device_class::FLAG_DO_COMMAND |
268                               i4_device_class::FLAG_END_COMMAND);
269     
270    if (redraw_later.waiting)
271    {
272      i4_time_dev.cancel_event(redraw_later.id);
273      redraw_later.waiting=i4_F;
274    }
275
276    if (g1_map_is_loaded())
277      g1_destroy_map();
278
279    g1_global_id.init();
280
281    g1_unload_object_defaults();
282
283    g1_resources.cleanup();
284    g1_unload_images();
285
286
287    g1_cwin_man->destroy_views();
288    g1_cwin_man->uninit();
289
290
291    r1_destroy_api(g1_render.r_api);   
292    g1_render.r_api=0;
293
294    g1_input.uninit();
295
296    g1_uninitialize_loaded_objects();
297
298    i4_application_class::uninit();
299  }
300
301  void choice_first_level();
302
303  char *name() { return "golgotha_app"; }
304} ;
305
306golgotha_app *g1_app=0;
307
308
309li_object *g1_pause(li_object *o, li_environment *env)
310{
311  g1_stop_sound_averages();
312
313  g1_resources.paused=!g1_resources.paused;
314  if (g1_map_is_loaded())
315    g1_get_map()->tick_time.get();
316  return 0;
317}
318
319li_object *g1_set_default_level(li_object *o, li_environment *env)
320{
321  strcpy(first_level, li_get_string(li_eval(li_car(o,env),env),env));
322  return 0;
323}
324
325
326void golgotha_app::pre_play_save()
327{
328  i4_file_class *out=i4_open(i4gets("play_savename"), I4_WRITE);
329  if (out)
330  {
331    g1_saver_class *save=new g1_saver_class(out);
332
333    g1_get_map()->save(save, G1_MAP_ALL);
334
335    if (save->begin_data_write())
336      g1_get_map()->save(save, G1_MAP_ALL);
337
338    delete save;
339
340    need_post_play_load=i4_T;
341  }
342}
343
344void golgotha_app::post_play_load()
345{
346  i4_str *old_name=new i4_str(g1_get_map()->get_filename());
347  if (g1_load_level(i4gets("play_savename"), 0))
348    g1_get_map()->set_filename(*old_name);
349
350  delete old_name;
351
352  need_post_play_load=i4_F;
353}
354
355
356void golgotha_app::do_options()
357{
358//   if (main_menu)
359//     delete main_menu;
360
361//   main_menu=new g1_option_window(wm->width(), wm->height(), wm->get_style(), this);
362//   wm->add_child(0,0,main_menu);
363}
364
365
366void golgotha_app::network_menu()
367{
368  if (main_menu)
369    delete main_menu;
370
371  main_menu=new g1_startup_window(wm->width(), wm->height(), wm->get_style(), protocol);
372  wm->add_child(0,0,main_menu);
373}
374
375void golgotha_app::help_screen(char *screen_name, int next_id)
376{
377  if (main_menu)
378    delete main_menu;
379
380  main_menu=new g1_help_screen_class(wm->width(), wm->height(), wm->get_style(),
381                                     i4gets(screen_name), next_id);
382
383  wm->add_child(0,0,main_menu);
384}
385
386void golgotha_app::plot_screen()
387{
388  if (main_menu)
389    delete main_menu;
390
391  main_menu=new g1_help_screen_class(wm->width(), wm->height(), wm->get_style(),
392                                     i4gets("plot_screen"), G1_MAIN_MENU);
393
394  wm->add_child(0,0,main_menu);
395}
396
397void golgotha_app::server_menu()
398{
399  if (main_menu)
400    delete main_menu;
401
402
403  main_menu=new g1_server_start_window(wm->width(), wm->height(),
404                                       wm->get_style(), protocol);
405  wm->add_child(0,0,main_menu);
406}
407
408void golgotha_app::client_wait_menu()
409{
410  if (main_menu)
411    delete main_menu;
412
413  main_menu=new g1_client_wait_window(wm->width(), wm->height(),
414                                      wm->get_style(),  protocol);
415  wm->add_child(0,0,main_menu);
416}
417
418
419
420void golgotha_app::do_main_menu()
421{
422
423  sw32 ids[]={ G1_START_NEW_GAME,
424               G1_NO_MESSAGE,
425               G1_NO_MESSAGE,
426
427               G1_NETWORK_MENU,
428               G1_OPTIONS,
429               G1_QUIT,
430               -1 };
431
432  if (main_menu)
433    delete main_menu;
434
435  main_menu=new g1_main_menu_class(wm->width(),
436                                   wm->height(),
437                                   this,
438                                   ids,
439                                   wm->get_style());
440                                   
441                                   
442  wm->add_child(0,0,main_menu);
443}
444
445li_symbol_ref fo_sym("File/Open");
446
447void check_fo()
448{
449  li_symbol *org=fo_sym.get();
450  li_symbol *news=li_get_symbol("File/Open");
451 
452  if (org!=news)
453    i4_warning("symbols off!");
454}
455
456void golgotha_app::receive_event(i4_event *ev)
457{
458  switch (ev->type())
459  {
460    case i4_event::DO_COMMAND :
461    {
462      fo_sym.get();
463
464      g1_cwin_man->receive_event(ev);     
465      char *cmd=((i4_do_command_event_class *)ev)->command;
466      li_symbol *s=li_get_symbol(cmd);
467      if (li_get_fun(s,0))
468        li_call(s);
469
470      g1_input.receive_event(ev);
471    } break;
472
473    case i4_event::END_COMMAND :
474    {
475      g1_cwin_man->receive_event(ev);
476      char cmd[200];
477      sprintf(cmd, "-%s",((i4_do_command_event_class *)ev)->command);
478      li_symbol *s=li_get_symbol(cmd);
479      if (li_get_fun(s,0))
480        li_call(cmd);
481      g1_input.receive_event(ev);
482    } break;
483     
484    case i4_event::USER_MESSAGE :
485    {
486      CAST_PTR(uev,i4_user_message_event_class,ev);
487      switch (uev->sub_type)
488      {
489       case G1_MAIN_MENU :
490          do_main_menu();
491          break;
492
493        case G1_NETWORK_MENU :
494          network_menu(); 
495          break;
496        case G1_SERVER_MENU :
497          server_menu();
498          break;
499        case G1_CLIENT_JOINED_MENU :
500          client_wait_menu();
501          break;
502
503        case G1_YOU_LOSE :
504          help_screen("youlose_screen", G1_QUIT);
505          break;
506         
507        case G1_YOU_WIN :
508          help_screen("youwin_screen", G1_QUIT);
509          break;         
510
511        case G1_HELP_SCREEN :
512          help_screen("help_screen", G1_RETURN_TO_GAME);
513          break;
514
515        case G1_START_HELP_SCREEN :
516          help_screen("help_screen", G1_START_NEW_GAME);
517          break;
518
519        case G1_PLOT_SCREEN :
520          plot_screen();
521          break;
522
523        case G1_START_NEW_GAME :
524          start_new_game();
525          break;
526
527        case G1_RETURN_TO_GAME :
528          return_to_game();
529          break;
530
531        case G1_OPTIONS :
532          do_options();
533          break;
534
535        case G1_QUIT :
536          quit();
537          break;
538        case G1_ESCAPE :
539          quit();
540          break;
541
542        case G1_MAP_CHANGED :
543          map_changed();
544          break;
545
546        case G1_GET_ROOT_IMAGE :
547        {
548          CAST_PTR(get, g1_get_root_image_event, ev);
549          get->result=display->get_screen();
550        } break;
551
552
553        case G1_REDRAW_LATER :
554        {
555          redraw_later.waiting=i4_F;
556          li_call("redraw_all");
557        } break;
558
559        case G1_PLAY_MOVIE :
560          if (g1_map_is_loaded())
561          {
562            pre_play_save();
563
564            if (g1_get_map()->start_movie())
565            {
566              playing_movie=i4_T;           
567              g1_resources.paused=i4_F;
568            }
569
570          } break;
571
572        case G1_STOP_MOVIE :
573        {
574          if (playing_movie)
575          {
576            if (g1_map_is_loaded())
577            {
578              g1_get_map()->stop_movie();
579             
580              post_play_load();
581            }
582
583            playing_movie=i4_F;
584
585            if (g1_current_controller.get() &&
586                g1_current_controller->view.get_view_mode()==G1_CAMERA_MODE)
587              g1_current_controller->view.suggest_camera_mode(G1_ACTION_MODE);
588          }
589         
590        } break;
591
592        case G1_GET_CURRENT_MOVIE :
593        {
594          if (g1_map_is_loaded())
595          {
596            CAST_PTR(mev, g1_get_current_movie_event, ev);
597            mev->mflow=g1_get_map()->current_movie;
598          }
599
600        } break;
601
602        case G1_INTERLACE_PIXEL :
603        {
604          g1_cwin_man->destroy_views();
605          g1_resources.render_window_expand_mode = R1_COPY_1x1_SCANLINE_SKIP;
606          g1_cwin_man->create_views();           
607        } break;
608
609        case G1_DOUBLE_PIXEL :
610        {
611          g1_cwin_man->destroy_views();
612          g1_resources.render_window_expand_mode = R1_COPY_2x2;
613          g1_cwin_man->create_views();           
614        } break;
615
616        case G1_NORMAL_PIXEL :
617        {
618          g1_cwin_man->destroy_views();
619          g1_resources.render_window_expand_mode = R1_COPY_1x1;
620          g1_cwin_man->create_views();           
621        } break;
622
623      }
624    } break;
625
626    default:
627      i4_application_class::receive_event(ev);
628  }
629}
630
631void golgotha_app::choice_first_level()
632{
633
634  for (int i=1; i<argc; i++)
635    if (argv[i]=="-f")
636    {
637      i4_os_string(*(argv+i+1), first_level, 80);
638      i++;
639    }
640    else if (argv[i]==i4_const_str("-edit"))
641    {
642      start_in_editor=1;
643    }
644    else if (argv[i]=="-eval")
645    {
646      i++;
647      char buf[1000];
648      i4_os_string(argv[i], buf, 1000);
649      char *s=buf;
650      li_eval(li_get_expression(s,0), 0);
651    }
652    else if (argv[i]=="-frame_lock")
653      frame_locked_mode=1;
654}
655
656
657
658static i4_event_handler_reference_class<i4_parent_window_class> loading_window;
659
660void golgotha_app::init()
661{
662  sw32 i;
663
664  for (i=0; i<argc; i++)
665  {
666    if (argv[i] == "-max_memory")
667    {
668      i++;
669      i4_const_str::iterator p(argv[i].begin());
670      _max_memory = (w32)p.read_number();
671    }
672  }
673
674
675  memory_init();
676
677
678  resource_init("resource.res",0);
679  strcpy(first_level, "test.level");
680  li_add_function("set_default_level", g1_set_default_level);
681
682  li_load("scheme/start.scm");
683
684  i4_image_class *im=i4_load_image("bitmaps/comic1.jpg");
685
686  display_init(); 
687
688  g1_sound_man.poll(i4_T);             // update sound effects (play next narative sfx)
689  g1_sound_man.loop_current_song=i4_T;
690
691
692  wm->set_background_color(0);
693
694
695
696  if (im)
697  {
698    loading_window=new i4_image_window_class(im, i4_T, i4_F);
699    wm->add_child(wm->width()/2-loading_window->width()/2,
700                  wm->height()/2-loading_window->height()/2,
701                  loading_window.get());
702  }
703  refresh();     // show something right away
704
705  char *font_fname=li_get_string(li_get_value("font"),0);
706  i4_image_class *fim=i4_load_image(font_fname);
707  if (!fim) i4_error("image load failed : %s", font_fname); 
708  i4_current_app->get_style()->font_hint->normal_font=new i4_anti_proportional_font_class(fim); 
709  delete fim;
710
711
712
713
714  choice_first_level();
715 
716  g1_render.r_api = r1_create_api(display);
717 
718  if (!g1_render.r_api)
719    i4_error("Could not initialize a rendering device"); 
720
721
722  g1_input.init(); 
723
724  g1_resources.load();
725  li_load("scheme/preferences.scm");
726 
727  i4_bool movie_time = i4_F;
728
729  for (i=0; i<argc; i++)
730  {
731    if (argv[i] == i4gets("movie_option"))
732      movie_time = i4_T;       
733  }
734
735  if (g1_render.r_api->get_render_device_flags() & R1_SOFTWARE)
736  {
737    //setup a timer and decide whether or not to do double pixel
738    //default is high res mode
739    int processor_speed = i4_get_clocks_per_second();
740 
741    g1_resources.render_window_expand_mode = R1_COPY_1x1;
742    /*
743    if (processor_speed > 170000000)
744            g1_resources.render_window_expand_mode = R1_COPY_1x1;
745    else
746    if (processor_speed > 140000000)
747      g1_resources.render_window_expand_mode = R1_COPY_1x1_SCANLINE_SKIP;
748    else   
749      g1_resources.render_window_expand_mode = R1_COPY_2x2;
750
751    g1_resources.radius_mode = g1_resource_class::VIEW_LOW;
752    */
753
754    if (movie_time)
755      g1_resources.radius_mode = g1_resource_class::VIEW_FAR;
756
757  }
758  else
759  {
760    //hardware rasterizer, view distance = far by default
761    g1_resources.radius_mode = g1_resource_class::VIEW_FAR;
762  }
763
764  s1_load();
765  g1_load_images();
766
767
768  g1_player_man.init_colors(&display->get_screen()->get_pal()->source, g1_render.r_api);
769
770  protocol=i4_get_first_protocol();
771
772  i4_graphical_style_class *style=wm->get_style();
773 
774
775  /*
776  style->color_hint->button.active.bright=(135<<8)|64;
777  style->color_hint->button.active.medium=(114<<8)|49;
778  style->color_hint->button.active.dark=(88<<8)|38;
779
780  style->color_hint->button.passive.bright=(120<<8)|64;
781  style->color_hint->button.passive.medium=(100<<8)|49;
782  style->color_hint->button.passive.dark=(70<<8)|38;
783  */
784
785  if (!g1_cwin_man)
786    g1_cwin_man=new g1_cwin_man_class;     
787
788  g1_cwin_man->init(wm, style, display->get_screen(), display, wm);
789  li_add_function("Pause", g1_pause);
790
791//   main_menu=new g1_help_screen_class(wm->width(), wm->height(), wm->get_style(),
792//                                      i4gets("startup_screen"), G1_PLOT_SCREEN);
793
794  main_menu=0;
795
796//   i4_const_str *tlist=i4_string_man.get_array("texture_array");
797//   g1_load_texture_list(tlist);
798//   i4_free(tlist);
799
800
801  start_new_game();
802  if (start_in_editor)
803    g1_cwin_man->set_edit_mode(i4_T);
804
805
806  i4_kernel.request_events(this,
807                           i4_device_class::FLAG_DO_COMMAND |
808                           i4_device_class::FLAG_END_COMMAND);
809     
810  //  do_main_menu();
811
812
813  // start game with startup screens
814//   if (!movie_time)
815//   {
816//     help_screen("startup_screen", G1_START_HELP_SCREEN);
817//   }
818//   else
819//   {
820//     start_new_game();
821//   }
822
823}
824 
825
826void golgotha_app::return_to_game()
827{
828  if (!g1_map_is_loaded())
829    start_new_game();
830  else if (main_menu)
831  {
832    delete main_menu;
833    main_menu=0;
834  }   
835}
836
837void golgotha_app::start_new_game()
838{
839  if (main_menu)
840  {
841    delete main_menu;
842    main_menu=0;
843  }
844
845  g1_cwin_man->destroy_views();
846 
847  int no_demo=1;
848  for (int i=1; i<argc; i++)
849  {
850    if (argv[i]=="-no_demo")
851      no_demo=1;
852    if (argv[i]=="-demo")
853      li_call("play_demo");
854    else if (argv[i]=="-df")
855    {
856      i++;
857      char fname[100];
858      i4_os_string(argv[i], fname,256);
859      li_call("play_demo", li_make_list(new li_string(fname), 0));           
860    }
861  }
862
863  // demo verision for sampler CD, play demo if not started already
864  if (!g1_playing_demo() && !no_demo)
865    li_call("play_demo");
866
867  if (!g1_playing_demo())
868    if (!g1_load_level(first_level))
869      i4_error("could not load level %s", first_level);
870
871
872  if (loading_window.get())
873    i4_kernel.delete_handler(loading_window.get());
874 
875  g1_cwin_man->create_views();
876
877  if (g1_map_is_loaded() && g1_get_map()->start_movie())
878  {
879    playing_movie=i4_T;           
880    g1_resources.paused=i4_F;
881   
882    if (g1_current_controller.get())
883      g1_current_controller->view.suggest_camera_mode(G1_CAMERA_MODE);
884
885  }
886
887  g1_sound_man.loop_current_song=i4_F;
888  g1_sound_man.next_song();
889}
890
891void i4_main(w32 argc, i4_const_str *argv)
892
893  golgotha_app app(argc, argv);
894  g1_app=&app;
895  app.run(); 
896}
897
898
Note: See TracBrowser for help on using the repository browser.