From c068f22329d5cc722622a2183bbb22eef2093df7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Aug 2026 11:16:07 +0200 Subject: initial import --- src/parsec/aud_bkgn.cpp | 1189 ++++++++++++ src/parsec/aud_comm.cpp | 523 ++++++ src/parsec/aud_game.cpp | 2773 +++++++++++++++++++++++++++ src/parsec/aud_glob.cpp | 53 + src/parsec/aud_sdlmixer.cpp | 603 ++++++ src/parsec/aud_supp.cpp | 150 ++ src/parsec/con_act.cpp | 3548 +++++++++++++++++++++++++++++++++++ src/parsec/con_aux.cpp | 429 +++++ src/parsec/con_cani.cpp | 627 +++++++ src/parsec/con_com.cpp | 1156 ++++++++++++ src/parsec/con_conf.cpp | 538 ++++++ src/parsec/con_ext.cpp | 1193 ++++++++++++ src/parsec/con_geom.cpp | 506 +++++ src/parsec/con_info.cpp | 2120 +++++++++++++++++++++ src/parsec/con_int.cpp | 405 ++++ src/parsec/con_kmap.cpp | 976 ++++++++++ src/parsec/con_list.cpp | 1265 +++++++++++++ src/parsec/con_load.cpp | 1626 ++++++++++++++++ src/parsec/con_main.cpp | 1986 ++++++++++++++++++++ src/parsec/con_path.cpp | 125 ++ src/parsec/con_rc.cpp | 420 +++++ src/parsec/con_say.cpp | 295 +++ src/parsec/con_shad.cpp | 583 ++++++ src/parsec/con_std.cpp | 166 ++ src/parsec/con_tani.cpp | 71 + src/parsec/d_glob.cpp | 38 + src/parsec/d_misc.cpp | 129 ++ src/parsec/do_bmap.cpp | 331 ++++ src/parsec/do_font.cpp | 535 ++++++ src/parsec/do_iter.cpp | 1772 +++++++++++++++++ src/parsec/do_misc.cpp | 313 +++ src/parsec/do_patch.cpp | 47 + src/parsec/e_callbk.cpp | 268 +++ src/parsec/e_colani.cpp | 227 +++ src/parsec/e_color.cpp | 757 ++++++++ src/parsec/e_demo.cpp | 1274 +++++++++++++ src/parsec/e_draw.cpp | 464 +++++ src/parsec/e_events.cpp | 351 ++++ src/parsec/e_getopt.cpp | 648 +++++++ src/parsec/e_global.cpp | 358 ++++ src/parsec/e_level.cpp | 374 ++++ src/parsec/e_loader.cpp | 1355 +++++++++++++ src/parsec/e_mouse.cpp | 131 ++ src/parsec/e_record.cpp | 1788 ++++++++++++++++++ src/parsec/e_replay.cpp | 367 ++++ src/parsec/e_shader.cpp | 709 +++++++ src/parsec/e_supp.cpp | 469 +++++ src/parsec/e_texani.cpp | 153 ++ src/parsec/e_vtxani.cpp | 554 ++++++ src/parsec/g_boot.cpp | 507 +++++ src/parsec/g_bot_cl.cpp | 1028 ++++++++++ src/parsec/g_camera.cpp | 644 +++++++ src/parsec/g_cloud.cpp | 307 +++ src/parsec/g_explod.cpp | 310 +++ src/parsec/g_gameloop.cpp | 1277 +++++++++++++ src/parsec/g_global.cpp | 160 ++ src/parsec/g_laser.cpp | 612 ++++++ src/parsec/g_planet.cpp | 573 ++++++ src/parsec/g_sfx.cpp | 716 +++++++ src/parsec/g_shkwav.cpp | 717 +++++++ src/parsec/g_stars.cpp | 756 ++++++++ src/parsec/g_stgate.cpp | 1653 ++++++++++++++++ src/parsec/g_supp.cpp | 679 +++++++ src/parsec/g_swarm.cpp | 513 +++++ src/parsec/g_telep.cpp | 2006 ++++++++++++++++++++ src/parsec/g_vapor.cpp | 633 +++++++ src/parsec/g_wfx.cpp | 1314 +++++++++++++ src/parsec/h_cockpt.cpp | 2529 +++++++++++++++++++++++++ src/parsec/h_drwhud.cpp | 953 ++++++++++ src/parsec/h_frmplt.cpp | 127 ++ src/parsec/h_global.cpp | 52 + src/parsec/h_radar.cpp | 617 ++++++ src/parsec/h_strmap.cpp | 2101 +++++++++++++++++++++ src/parsec/h_supp.cpp | 608 ++++++ src/parsec/h_text.cpp | 556 ++++++ src/parsec/img_3df.cpp | 776 ++++++++ src/parsec/img_api.cpp | 253 +++ src/parsec/img_conv.cpp | 644 +++++++ src/parsec/img_jpg.cpp | 65 + src/parsec/img_load.cpp | 615 ++++++ src/parsec/img_supp.cpp | 259 +++ src/parsec/img_tga.cpp | 313 +++ src/parsec/include/aud_bkgn.h | 29 + src/parsec/include/aud_comm.h | 16 + src/parsec/include/aud_defs.h | 122 ++ src/parsec/include/aud_game.h | 236 +++ src/parsec/include/aud_glob.h | 16 + src/parsec/include/aud_subh.h | 160 ++ src/parsec/include/aud_supp.h | 129 ++ src/parsec/include/con_act.h | 239 +++ src/parsec/include/con_aux.h | 331 ++++ src/parsec/include/con_cani.h | 16 + src/parsec/include/con_com.h | 71 + src/parsec/include/con_conf.h | 36 + src/parsec/include/con_ext.h | 91 + src/parsec/include/con_geom.h | 15 + src/parsec/include/con_info.h | 63 + src/parsec/include/con_int.h | 59 + src/parsec/include/con_kmap.h | 49 + src/parsec/include/con_list.h | 34 + src/parsec/include/con_load.h | 16 + src/parsec/include/con_main.h | 157 ++ src/parsec/include/con_path.h | 15 + src/parsec/include/con_rc.h | 16 + src/parsec/include/con_say.h | 41 + src/parsec/include/con_shad.h | 26 + src/parsec/include/con_std.h | 127 ++ src/parsec/include/con_tani.h | 16 + src/parsec/include/d_bmap.h | 26 + src/parsec/include/d_font.h | 24 + src/parsec/include/d_fontt.h | 435 +++++ src/parsec/include/d_glob.h | 31 + src/parsec/include/d_iter.h | 37 + src/parsec/include/d_misc.h | 43 + src/parsec/include/d_patch.h | 17 + src/parsec/include/do_bmap.h | 28 + src/parsec/include/do_font.h | 29 + src/parsec/include/do_iter.h | 34 + src/parsec/include/do_misc.h | 21 + src/parsec/include/do_patch.h | 15 + src/parsec/include/e_callbk.h | 62 + src/parsec/include/e_colani.h | 34 + src/parsec/include/e_color.h | 94 + src/parsec/include/e_demo.h | 55 + src/parsec/include/e_draw.h | 55 + src/parsec/include/e_events.h | 66 + src/parsec/include/e_evtdef.h | 48 + src/parsec/include/e_getopt.h | 55 + src/parsec/include/e_global.h | 177 ++ src/parsec/include/e_level.h | 19 + src/parsec/include/e_loader.h | 20 + src/parsec/include/e_mouse.h | 51 + src/parsec/include/e_record.h | 79 + src/parsec/include/e_replay.h | 17 + src/parsec/include/e_shader.h | 69 + src/parsec/include/e_supp.h | 32 + src/parsec/include/e_texani.h | 34 + src/parsec/include/e_vtxani.h | 17 + src/parsec/include/g_boot.h | 19 + src/parsec/include/g_bot_cl.h | 404 ++++ src/parsec/include/g_camera.h | 32 + src/parsec/include/g_cloud.h | 20 + src/parsec/include/g_explod.h | 16 + src/parsec/include/g_gameloop.h | 16 + src/parsec/include/g_global.h | 119 ++ src/parsec/include/g_laser.h | 17 + src/parsec/include/g_main_cl.h | 258 +++ src/parsec/include/g_planet.h | 47 + src/parsec/include/g_sfx.h | 35 + src/parsec/include/g_shkwav.h | 16 + src/parsec/include/g_stars.h | 20 + src/parsec/include/g_supp.h | 37 + src/parsec/include/g_swarm.h | 20 + src/parsec/include/g_telep.h | 79 + src/parsec/include/g_vapor.h | 16 + src/parsec/include/g_wfx.h | 51 + src/parsec/include/h_cockpt.h | 78 + src/parsec/include/h_drwhud.h | 30 + src/parsec/include/h_frmplt.h | 17 + src/parsec/include/h_global.h | 47 + src/parsec/include/h_radar.h | 28 + src/parsec/include/h_strmap.h | 35 + src/parsec/include/h_supp.h | 40 + src/parsec/include/h_text.h | 23 + src/parsec/include/il_joy.h | 25 + src/parsec/include/il_mouse.h | 19 + src/parsec/include/il_supp.h | 18 + src/parsec/include/img_3df.h | 28 + src/parsec/include/img_api.h | 78 + src/parsec/include/img_conv.h | 61 + src/parsec/include/img_jpg.h | 16 + src/parsec/include/img_load.h | 45 + src/parsec/include/img_supp.h | 20 + src/parsec/include/img_tga.h | 16 + src/parsec/include/inp_comm.h | 16 + src/parsec/include/inp_defs.h | 220 +++ src/parsec/include/inp_glob.h | 26 + src/parsec/include/inp_init.h | 17 + src/parsec/include/inp_keyn.h | 109 ++ src/parsec/include/inp_sdl.h | 26 + src/parsec/include/inp_subh.h | 36 + src/parsec/include/inp_user.h | 42 + src/parsec/include/isdl_joy.h | 30 + src/parsec/include/isdl_keydf.h | 89 + src/parsec/include/isdl_keyn.h | 117 ++ src/parsec/include/isdl_mouse.h | 19 + src/parsec/include/isdl_supp.h | 18 + src/parsec/include/m_button.h | 92 + src/parsec/include/m_list.h | 46 + src/parsec/include/m_logo.h | 21 + src/parsec/include/m_main.h | 85 + src/parsec/include/m_option.h | 67 + src/parsec/include/m_status.h | 21 + src/parsec/include/m_viewer.h | 42 + src/parsec/include/net_conn.h | 34 + src/parsec/include/net_game.h | 92 + src/parsec/include/net_game_gmsv.h | 30 + src/parsec/include/net_game_peer.h | 60 + src/parsec/include/net_glob.h | 144 ++ src/parsec/include/net_gmsv.h | 46 + src/parsec/include/net_pckt_peer.h | 23 + src/parsec/include/net_peer.h | 40 + src/parsec/include/net_prediction.h | 93 + src/parsec/include/net_rmev.h | 95 + src/parsec/include/net_rmev_gmsv.h | 20 + src/parsec/include/net_rmev_peer.h | 21 + src/parsec/include/net_serv.h | 77 + src/parsec/include/net_subh.h | 167 ++ src/parsec/include/net_udp.h | 33 + src/parsec/include/net_udpdf.h | 31 + src/parsec/include/net_univ.h | 40 + src/parsec/include/net_util_cl.h | 29 + src/parsec/include/nl_udp.h | 19 + src/parsec/include/nw_udp.h | 27 + src/parsec/include/obj_ani.h | 19 + src/parsec/include/obj_coll.h | 16 + src/parsec/include/obj_comm.h | 21 + src/parsec/include/obj_ctrl.h | 132 ++ src/parsec/include/obj_expl.h | 24 + src/parsec/include/obj_game.h | 53 + src/parsec/include/obj_iter.h | 22 + src/parsec/include/obj_part.h | 32 + src/parsec/include/obj_vani.h | 20 + src/parsec/include/obj_xtra.h | 21 + src/parsec/include/part_ani.h | 22 + src/parsec/include/part_api.h | 435 +++++ src/parsec/include/part_def.h | 29 + src/parsec/include/part_sys.h | 25 + src/parsec/include/r_gl.h | 93 + src/parsec/include/r_glob.h | 71 + src/parsec/include/r_obj.h | 21 + src/parsec/include/r_part.h | 20 + src/parsec/include/r_patch.h | 20 + src/parsec/include/r_perf.h | 22 + src/parsec/include/r_sfx.h | 21 + src/parsec/include/r_supp.h | 19 + src/parsec/include/ro_api.h | 84 + src/parsec/include/ro_obj.h | 19 + src/parsec/include/ro_objmc.h | 156 ++ src/parsec/include/ro_part.h | 17 + src/parsec/include/ro_patch.h | 17 + src/parsec/include/ro_perf.h | 19 + src/parsec/include/ro_poly.h | 18 + src/parsec/include/ro_sfx.h | 18 + src/parsec/include/ro_supp.h | 62 + src/parsec/include/sl_err.h | 21 + src/parsec/include/sl_main.h | 18 + src/parsec/include/sl_msg.h | 18 + src/parsec/include/sl_opt.h | 16 + src/parsec/include/snd_api.h | 49 + src/parsec/include/snd_wav.h | 20 + src/parsec/include/sys_bind.h | 36 + src/parsec/include/sys_conv.h | 16 + src/parsec/include/sys_err.h | 40 + src/parsec/include/sys_glob.h | 16 + src/parsec/include/sys_msg.h | 41 + src/parsec/include/sys_subh.h | 46 + src/parsec/include/t_pack.h | 14 + src/parsec/include/vid_defs.h | 84 + src/parsec/include/vid_glob.h | 108 ++ src/parsec/include/vid_init.h | 30 + src/parsec/include/vid_plug.h | 17 + src/parsec/include/vid_subh.h | 42 + src/parsec/include/vid_supp.h | 18 + src/parsec/include/vsdl_buffo.h | 18 + src/parsec/include/vsdl_inito.h | 18 + src/parsec/include/vsdl_ogl.h | 41 + src/parsec/include/vsdl_suppo.h | 23 + src/parsec/inp_comm.cpp | 353 ++++ src/parsec/inp_glob.cpp | 68 + src/parsec/inp_init.cpp | 84 + src/parsec/inp_sdl.cpp | 769 ++++++++ src/parsec/inp_user.cpp | 1028 ++++++++++ src/parsec/isdl_joy.cpp | 574 ++++++ src/parsec/isdl_mouse.cpp | 130 ++ src/parsec/isdl_supp.cpp | 458 +++++ src/parsec/m_button.cpp | 893 +++++++++ src/parsec/m_list.cpp | 1030 ++++++++++ src/parsec/m_logo.cpp | 343 ++++ src/parsec/m_main.cpp | 1980 +++++++++++++++++++ src/parsec/m_option.cpp | 1769 +++++++++++++++++ src/parsec/m_status.cpp | 475 +++++ src/parsec/m_viewer.cpp | 1220 ++++++++++++ src/parsec/net_conn.cpp | 476 +++++ src/parsec/net_game.cpp | 1304 +++++++++++++ src/parsec/net_game_gmsv.cpp | 268 +++ src/parsec/net_game_peer.cpp | 571 ++++++ src/parsec/net_glob.cpp | 199 ++ src/parsec/net_gmsv.cpp | 970 ++++++++++ src/parsec/net_pckt.cpp | 63 + src/parsec/net_pckt_peer.cpp | 860 +++++++++ src/parsec/net_peer.cpp | 1457 ++++++++++++++ src/parsec/net_prediction.cpp | 194 ++ src/parsec/net_rmev.cpp | 1284 +++++++++++++ src/parsec/net_rmev_gmsv.cpp | 652 +++++++ src/parsec/net_rmev_peer.cpp | 280 +++ src/parsec/net_serv.cpp | 2538 +++++++++++++++++++++++++ src/parsec/net_udp.cpp | 1430 ++++++++++++++ src/parsec/net_univ.cpp | 132 ++ src/parsec/net_util_cl.cpp | 288 +++ src/parsec/nl_udp.cpp | 333 ++++ src/parsec/nw_udp.cpp | 272 +++ src/parsec/obj_ani.cpp | 460 +++++ src/parsec/obj_coll.cpp | 1733 +++++++++++++++++ src/parsec/obj_comm.cpp | 522 ++++++ src/parsec/obj_ctrl.cpp | 1154 ++++++++++++ src/parsec/obj_expl.cpp | 439 +++++ src/parsec/obj_game.cpp | 885 +++++++++ src/parsec/obj_iter.cpp | 1357 ++++++++++++++ src/parsec/obj_part.cpp | 1040 ++++++++++ src/parsec/obj_vani.cpp | 389 ++++ src/parsec/obj_xtra.cpp | 618 ++++++ src/parsec/part_ani.cpp | 1065 +++++++++++ src/parsec/part_api.cpp | 1462 +++++++++++++++ src/parsec/part_def.cpp | 1241 ++++++++++++ src/parsec/part_sys.cpp | 1281 +++++++++++++ src/parsec/r_glob.cpp | 38 + src/parsec/ro_api.cpp | 772 ++++++++ src/parsec/ro_obj.cpp | 1147 +++++++++++ src/parsec/ro_part.cpp | 582 ++++++ src/parsec/ro_patch.cpp | 89 + src/parsec/ro_perf.cpp | 83 + src/parsec/ro_poly.cpp | 755 ++++++++ src/parsec/ro_sfx.cpp | 1020 ++++++++++ src/parsec/ro_supp.cpp | 1423 ++++++++++++++ src/parsec/sl_err.cpp | 259 +++ src/parsec/sl_main.cpp | 423 +++++ src/parsec/sl_msg.cpp | 273 +++ src/parsec/sl_opt.cpp | 441 +++++ src/parsec/snd_api.cpp | 144 ++ src/parsec/snd_wav.cpp | 449 +++++ src/parsec/sys_bind.cpp | 136 ++ src/parsec/sys_conv.cpp | 299 +++ src/parsec/sys_glob.cpp | 42 + src/parsec/t_pack.cpp | 769 ++++++++ src/parsec/vid_glob.cpp | 200 ++ src/parsec/vid_init.cpp | 582 ++++++ src/parsec/vid_plug.cpp | 174 ++ src/parsec/vid_supp.cpp | 287 +++ src/parsec/vsdl_buffo.cpp | 174 ++ src/parsec/vsdl_inito.cpp | 232 +++ src/parsec/vsdl_ogl.cpp | 864 +++++++++ src/parsec/vsdl_suppo.cpp | 236 +++ src/parsec/win_rc/sw_rsrc.rc | 72 + 344 files changed, 122241 insertions(+) create mode 100644 src/parsec/aud_bkgn.cpp create mode 100644 src/parsec/aud_comm.cpp create mode 100644 src/parsec/aud_game.cpp create mode 100644 src/parsec/aud_glob.cpp create mode 100644 src/parsec/aud_sdlmixer.cpp create mode 100644 src/parsec/aud_supp.cpp create mode 100644 src/parsec/con_act.cpp create mode 100644 src/parsec/con_aux.cpp create mode 100644 src/parsec/con_cani.cpp create mode 100644 src/parsec/con_com.cpp create mode 100644 src/parsec/con_conf.cpp create mode 100644 src/parsec/con_ext.cpp create mode 100644 src/parsec/con_geom.cpp create mode 100644 src/parsec/con_info.cpp create mode 100644 src/parsec/con_int.cpp create mode 100644 src/parsec/con_kmap.cpp create mode 100644 src/parsec/con_list.cpp create mode 100644 src/parsec/con_load.cpp create mode 100644 src/parsec/con_main.cpp create mode 100644 src/parsec/con_path.cpp create mode 100644 src/parsec/con_rc.cpp create mode 100644 src/parsec/con_say.cpp create mode 100644 src/parsec/con_shad.cpp create mode 100644 src/parsec/con_std.cpp create mode 100644 src/parsec/con_tani.cpp create mode 100644 src/parsec/d_glob.cpp create mode 100644 src/parsec/d_misc.cpp create mode 100644 src/parsec/do_bmap.cpp create mode 100644 src/parsec/do_font.cpp create mode 100644 src/parsec/do_iter.cpp create mode 100644 src/parsec/do_misc.cpp create mode 100644 src/parsec/do_patch.cpp create mode 100644 src/parsec/e_callbk.cpp create mode 100644 src/parsec/e_colani.cpp create mode 100644 src/parsec/e_color.cpp create mode 100644 src/parsec/e_demo.cpp create mode 100644 src/parsec/e_draw.cpp create mode 100644 src/parsec/e_events.cpp create mode 100644 src/parsec/e_getopt.cpp create mode 100644 src/parsec/e_global.cpp create mode 100644 src/parsec/e_level.cpp create mode 100644 src/parsec/e_loader.cpp create mode 100644 src/parsec/e_mouse.cpp create mode 100644 src/parsec/e_record.cpp create mode 100644 src/parsec/e_replay.cpp create mode 100644 src/parsec/e_shader.cpp create mode 100644 src/parsec/e_supp.cpp create mode 100644 src/parsec/e_texani.cpp create mode 100644 src/parsec/e_vtxani.cpp create mode 100644 src/parsec/g_boot.cpp create mode 100644 src/parsec/g_bot_cl.cpp create mode 100644 src/parsec/g_camera.cpp create mode 100644 src/parsec/g_cloud.cpp create mode 100644 src/parsec/g_explod.cpp create mode 100644 src/parsec/g_gameloop.cpp create mode 100644 src/parsec/g_global.cpp create mode 100644 src/parsec/g_laser.cpp create mode 100644 src/parsec/g_planet.cpp create mode 100644 src/parsec/g_sfx.cpp create mode 100644 src/parsec/g_shkwav.cpp create mode 100644 src/parsec/g_stars.cpp create mode 100644 src/parsec/g_stgate.cpp create mode 100644 src/parsec/g_supp.cpp create mode 100644 src/parsec/g_swarm.cpp create mode 100644 src/parsec/g_telep.cpp create mode 100644 src/parsec/g_vapor.cpp create mode 100644 src/parsec/g_wfx.cpp create mode 100644 src/parsec/h_cockpt.cpp create mode 100644 src/parsec/h_drwhud.cpp create mode 100644 src/parsec/h_frmplt.cpp create mode 100644 src/parsec/h_global.cpp create mode 100644 src/parsec/h_radar.cpp create mode 100644 src/parsec/h_strmap.cpp create mode 100644 src/parsec/h_supp.cpp create mode 100644 src/parsec/h_text.cpp create mode 100644 src/parsec/img_3df.cpp create mode 100644 src/parsec/img_api.cpp create mode 100644 src/parsec/img_conv.cpp create mode 100644 src/parsec/img_jpg.cpp create mode 100644 src/parsec/img_load.cpp create mode 100644 src/parsec/img_supp.cpp create mode 100644 src/parsec/img_tga.cpp create mode 100644 src/parsec/include/aud_bkgn.h create mode 100644 src/parsec/include/aud_comm.h create mode 100644 src/parsec/include/aud_defs.h create mode 100644 src/parsec/include/aud_game.h create mode 100644 src/parsec/include/aud_glob.h create mode 100644 src/parsec/include/aud_subh.h create mode 100644 src/parsec/include/aud_supp.h create mode 100644 src/parsec/include/con_act.h create mode 100644 src/parsec/include/con_aux.h create mode 100644 src/parsec/include/con_cani.h create mode 100644 src/parsec/include/con_com.h create mode 100644 src/parsec/include/con_conf.h create mode 100644 src/parsec/include/con_ext.h create mode 100644 src/parsec/include/con_geom.h create mode 100644 src/parsec/include/con_info.h create mode 100644 src/parsec/include/con_int.h create mode 100644 src/parsec/include/con_kmap.h create mode 100644 src/parsec/include/con_list.h create mode 100644 src/parsec/include/con_load.h create mode 100644 src/parsec/include/con_main.h create mode 100644 src/parsec/include/con_path.h create mode 100644 src/parsec/include/con_rc.h create mode 100644 src/parsec/include/con_say.h create mode 100644 src/parsec/include/con_shad.h create mode 100644 src/parsec/include/con_std.h create mode 100644 src/parsec/include/con_tani.h create mode 100644 src/parsec/include/d_bmap.h create mode 100644 src/parsec/include/d_font.h create mode 100644 src/parsec/include/d_fontt.h create mode 100644 src/parsec/include/d_glob.h create mode 100644 src/parsec/include/d_iter.h create mode 100644 src/parsec/include/d_misc.h create mode 100644 src/parsec/include/d_patch.h create mode 100644 src/parsec/include/do_bmap.h create mode 100644 src/parsec/include/do_font.h create mode 100644 src/parsec/include/do_iter.h create mode 100644 src/parsec/include/do_misc.h create mode 100644 src/parsec/include/do_patch.h create mode 100644 src/parsec/include/e_callbk.h create mode 100644 src/parsec/include/e_colani.h create mode 100644 src/parsec/include/e_color.h create mode 100644 src/parsec/include/e_demo.h create mode 100644 src/parsec/include/e_draw.h create mode 100644 src/parsec/include/e_events.h create mode 100644 src/parsec/include/e_evtdef.h create mode 100644 src/parsec/include/e_getopt.h create mode 100644 src/parsec/include/e_global.h create mode 100644 src/parsec/include/e_level.h create mode 100644 src/parsec/include/e_loader.h create mode 100644 src/parsec/include/e_mouse.h create mode 100644 src/parsec/include/e_record.h create mode 100644 src/parsec/include/e_replay.h create mode 100644 src/parsec/include/e_shader.h create mode 100644 src/parsec/include/e_supp.h create mode 100644 src/parsec/include/e_texani.h create mode 100644 src/parsec/include/e_vtxani.h create mode 100644 src/parsec/include/g_boot.h create mode 100644 src/parsec/include/g_bot_cl.h create mode 100644 src/parsec/include/g_camera.h create mode 100644 src/parsec/include/g_cloud.h create mode 100644 src/parsec/include/g_explod.h create mode 100644 src/parsec/include/g_gameloop.h create mode 100644 src/parsec/include/g_global.h create mode 100644 src/parsec/include/g_laser.h create mode 100644 src/parsec/include/g_main_cl.h create mode 100644 src/parsec/include/g_planet.h create mode 100644 src/parsec/include/g_sfx.h create mode 100644 src/parsec/include/g_shkwav.h create mode 100644 src/parsec/include/g_stars.h create mode 100644 src/parsec/include/g_supp.h create mode 100644 src/parsec/include/g_swarm.h create mode 100644 src/parsec/include/g_telep.h create mode 100644 src/parsec/include/g_vapor.h create mode 100644 src/parsec/include/g_wfx.h create mode 100644 src/parsec/include/h_cockpt.h create mode 100644 src/parsec/include/h_drwhud.h create mode 100644 src/parsec/include/h_frmplt.h create mode 100644 src/parsec/include/h_global.h create mode 100644 src/parsec/include/h_radar.h create mode 100644 src/parsec/include/h_strmap.h create mode 100644 src/parsec/include/h_supp.h create mode 100644 src/parsec/include/h_text.h create mode 100644 src/parsec/include/il_joy.h create mode 100644 src/parsec/include/il_mouse.h create mode 100644 src/parsec/include/il_supp.h create mode 100644 src/parsec/include/img_3df.h create mode 100644 src/parsec/include/img_api.h create mode 100644 src/parsec/include/img_conv.h create mode 100644 src/parsec/include/img_jpg.h create mode 100644 src/parsec/include/img_load.h create mode 100644 src/parsec/include/img_supp.h create mode 100644 src/parsec/include/img_tga.h create mode 100644 src/parsec/include/inp_comm.h create mode 100644 src/parsec/include/inp_defs.h create mode 100644 src/parsec/include/inp_glob.h create mode 100644 src/parsec/include/inp_init.h create mode 100755 src/parsec/include/inp_keyn.h create mode 100644 src/parsec/include/inp_sdl.h create mode 100644 src/parsec/include/inp_subh.h create mode 100644 src/parsec/include/inp_user.h create mode 100644 src/parsec/include/isdl_joy.h create mode 100644 src/parsec/include/isdl_keydf.h create mode 100644 src/parsec/include/isdl_keyn.h create mode 100644 src/parsec/include/isdl_mouse.h create mode 100644 src/parsec/include/isdl_supp.h create mode 100644 src/parsec/include/m_button.h create mode 100644 src/parsec/include/m_list.h create mode 100644 src/parsec/include/m_logo.h create mode 100644 src/parsec/include/m_main.h create mode 100644 src/parsec/include/m_option.h create mode 100644 src/parsec/include/m_status.h create mode 100644 src/parsec/include/m_viewer.h create mode 100644 src/parsec/include/net_conn.h create mode 100644 src/parsec/include/net_game.h create mode 100644 src/parsec/include/net_game_gmsv.h create mode 100644 src/parsec/include/net_game_peer.h create mode 100644 src/parsec/include/net_glob.h create mode 100644 src/parsec/include/net_gmsv.h create mode 100644 src/parsec/include/net_pckt_peer.h create mode 100644 src/parsec/include/net_peer.h create mode 100644 src/parsec/include/net_prediction.h create mode 100644 src/parsec/include/net_rmev.h create mode 100644 src/parsec/include/net_rmev_gmsv.h create mode 100644 src/parsec/include/net_rmev_peer.h create mode 100644 src/parsec/include/net_serv.h create mode 100644 src/parsec/include/net_subh.h create mode 100644 src/parsec/include/net_udp.h create mode 100644 src/parsec/include/net_udpdf.h create mode 100644 src/parsec/include/net_univ.h create mode 100644 src/parsec/include/net_util_cl.h create mode 100644 src/parsec/include/nl_udp.h create mode 100644 src/parsec/include/nw_udp.h create mode 100644 src/parsec/include/obj_ani.h create mode 100644 src/parsec/include/obj_coll.h create mode 100644 src/parsec/include/obj_comm.h create mode 100644 src/parsec/include/obj_ctrl.h create mode 100644 src/parsec/include/obj_expl.h create mode 100644 src/parsec/include/obj_game.h create mode 100644 src/parsec/include/obj_iter.h create mode 100644 src/parsec/include/obj_part.h create mode 100644 src/parsec/include/obj_vani.h create mode 100644 src/parsec/include/obj_xtra.h create mode 100644 src/parsec/include/part_ani.h create mode 100644 src/parsec/include/part_api.h create mode 100644 src/parsec/include/part_def.h create mode 100644 src/parsec/include/part_sys.h create mode 100644 src/parsec/include/r_gl.h create mode 100644 src/parsec/include/r_glob.h create mode 100644 src/parsec/include/r_obj.h create mode 100644 src/parsec/include/r_part.h create mode 100644 src/parsec/include/r_patch.h create mode 100644 src/parsec/include/r_perf.h create mode 100644 src/parsec/include/r_sfx.h create mode 100644 src/parsec/include/r_supp.h create mode 100644 src/parsec/include/ro_api.h create mode 100644 src/parsec/include/ro_obj.h create mode 100644 src/parsec/include/ro_objmc.h create mode 100644 src/parsec/include/ro_part.h create mode 100644 src/parsec/include/ro_patch.h create mode 100644 src/parsec/include/ro_perf.h create mode 100644 src/parsec/include/ro_poly.h create mode 100644 src/parsec/include/ro_sfx.h create mode 100644 src/parsec/include/ro_supp.h create mode 100644 src/parsec/include/sl_err.h create mode 100644 src/parsec/include/sl_main.h create mode 100644 src/parsec/include/sl_msg.h create mode 100644 src/parsec/include/sl_opt.h create mode 100644 src/parsec/include/snd_api.h create mode 100644 src/parsec/include/snd_wav.h create mode 100644 src/parsec/include/sys_bind.h create mode 100644 src/parsec/include/sys_conv.h create mode 100644 src/parsec/include/sys_err.h create mode 100644 src/parsec/include/sys_glob.h create mode 100644 src/parsec/include/sys_msg.h create mode 100644 src/parsec/include/sys_subh.h create mode 100644 src/parsec/include/t_pack.h create mode 100644 src/parsec/include/vid_defs.h create mode 100644 src/parsec/include/vid_glob.h create mode 100644 src/parsec/include/vid_init.h create mode 100644 src/parsec/include/vid_plug.h create mode 100644 src/parsec/include/vid_subh.h create mode 100644 src/parsec/include/vid_supp.h create mode 100644 src/parsec/include/vsdl_buffo.h create mode 100644 src/parsec/include/vsdl_inito.h create mode 100644 src/parsec/include/vsdl_ogl.h create mode 100644 src/parsec/include/vsdl_suppo.h create mode 100644 src/parsec/inp_comm.cpp create mode 100644 src/parsec/inp_glob.cpp create mode 100644 src/parsec/inp_init.cpp create mode 100644 src/parsec/inp_sdl.cpp create mode 100644 src/parsec/inp_user.cpp create mode 100644 src/parsec/isdl_joy.cpp create mode 100644 src/parsec/isdl_mouse.cpp create mode 100644 src/parsec/isdl_supp.cpp create mode 100644 src/parsec/m_button.cpp create mode 100644 src/parsec/m_list.cpp create mode 100644 src/parsec/m_logo.cpp create mode 100644 src/parsec/m_main.cpp create mode 100644 src/parsec/m_option.cpp create mode 100644 src/parsec/m_status.cpp create mode 100644 src/parsec/m_viewer.cpp create mode 100644 src/parsec/net_conn.cpp create mode 100644 src/parsec/net_game.cpp create mode 100644 src/parsec/net_game_gmsv.cpp create mode 100644 src/parsec/net_game_peer.cpp create mode 100644 src/parsec/net_glob.cpp create mode 100644 src/parsec/net_gmsv.cpp create mode 100644 src/parsec/net_pckt.cpp create mode 100644 src/parsec/net_pckt_peer.cpp create mode 100644 src/parsec/net_peer.cpp create mode 100644 src/parsec/net_prediction.cpp create mode 100644 src/parsec/net_rmev.cpp create mode 100644 src/parsec/net_rmev_gmsv.cpp create mode 100644 src/parsec/net_rmev_peer.cpp create mode 100644 src/parsec/net_serv.cpp create mode 100644 src/parsec/net_udp.cpp create mode 100644 src/parsec/net_univ.cpp create mode 100644 src/parsec/net_util_cl.cpp create mode 100644 src/parsec/nl_udp.cpp create mode 100644 src/parsec/nw_udp.cpp create mode 100644 src/parsec/obj_ani.cpp create mode 100644 src/parsec/obj_coll.cpp create mode 100644 src/parsec/obj_comm.cpp create mode 100644 src/parsec/obj_ctrl.cpp create mode 100644 src/parsec/obj_expl.cpp create mode 100644 src/parsec/obj_game.cpp create mode 100644 src/parsec/obj_iter.cpp create mode 100644 src/parsec/obj_part.cpp create mode 100644 src/parsec/obj_vani.cpp create mode 100644 src/parsec/obj_xtra.cpp create mode 100644 src/parsec/part_ani.cpp create mode 100644 src/parsec/part_api.cpp create mode 100644 src/parsec/part_def.cpp create mode 100644 src/parsec/part_sys.cpp create mode 100644 src/parsec/r_glob.cpp create mode 100644 src/parsec/ro_api.cpp create mode 100644 src/parsec/ro_obj.cpp create mode 100644 src/parsec/ro_part.cpp create mode 100644 src/parsec/ro_patch.cpp create mode 100644 src/parsec/ro_perf.cpp create mode 100644 src/parsec/ro_poly.cpp create mode 100644 src/parsec/ro_sfx.cpp create mode 100644 src/parsec/ro_supp.cpp create mode 100644 src/parsec/sl_err.cpp create mode 100644 src/parsec/sl_main.cpp create mode 100644 src/parsec/sl_msg.cpp create mode 100644 src/parsec/sl_opt.cpp create mode 100644 src/parsec/snd_api.cpp create mode 100644 src/parsec/snd_wav.cpp create mode 100644 src/parsec/sys_bind.cpp create mode 100644 src/parsec/sys_conv.cpp create mode 100644 src/parsec/sys_glob.cpp create mode 100644 src/parsec/t_pack.cpp create mode 100644 src/parsec/vid_glob.cpp create mode 100644 src/parsec/vid_init.cpp create mode 100644 src/parsec/vid_plug.cpp create mode 100644 src/parsec/vid_supp.cpp create mode 100644 src/parsec/vsdl_buffo.cpp create mode 100644 src/parsec/vsdl_inito.cpp create mode 100644 src/parsec/vsdl_ogl.cpp create mode 100644 src/parsec/vsdl_suppo.cpp create mode 100644 src/parsec/win_rc/sw_rsrc.rc (limited to 'src/parsec') diff --git a/src/parsec/aud_bkgn.cpp b/src/parsec/aud_bkgn.cpp new file mode 100644 index 0000000..d0b6fb5 --- /dev/null +++ b/src/parsec/aud_bkgn.cpp @@ -0,0 +1,1189 @@ +/* + * PARSEC - + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:33 $ + * + * Orginally written by: + * Copyright (c) Clemens Beer 1999 + + Updated by: + Copyright (c) 2003 Sivaram Velauthapillai (sivaram33@hotmail.com or koalabear33@yahoo.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +UPDATES: +August 10, 2003 + + MP3 support dropped; instead of loading mp3 files, game now loads ogg files +*/ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" + +// local module header +#include "aud_bkgn.h" + +// proprietary module headers +#include "aud_game.h" +#include "aud_supp.h" +#include "con_arg.h" +#include "con_aux.h" +#include "con_com.h" +#include "con_int.h" +#include "con_main.h" +#include "e_callbk.h" +#include "e_events.h" +#include "g_supp.h" +#include "snd_api.h" +#include "sys_file.h" + + +#define NUM_AUDIO_CD_TRACKS 9 +#define NUM_GAMESFX_STREAMS 9 + + +// defined background item types ---------------------------------------------- +// +#define BKGN_ITEM_TYPE_SAMPLE 0x0001 +#define BKGN_ITEM_TYPE_CDTRACK 0x0002 +#define BKGN_ITEM_TYPE_STREAM 0x0004 +#define BKGN_ITEM_TYPE_SILENCE 0x0008 + + +// generic background item structure ------------------------------------------ +// +struct BKGN_Item_s { + BKGN_Item_s* next; + dword type; // type of background item + dword id; // id (sampleid, cdtrack, ...) of background item + char* filename; // filename if item is an audiostream + int groupnext; // don't shuffle after completing this item + int fadein_start; // seconds to start the fadein + int fadein_end; // seconds to end the fadein (full volume) + int fadeout_start; // seconds to start the fadeout + int fadeout_end; // seconds to end the fadeout + int _mksiz32; +}; + + +// module local globals ------------------------------------------------------- +// +static BKGN_Item_s* BKGN_items; +static BKGN_Item_s* BKGN_items_head; +static int BKGN_nVoice; +static int BKGN_nNumItems; +static int BKGN_nCurrentItem; +static int BKGN_Started; +static int BKGN_shuffle = TRUE; + + + + +// console texts -------------------------------------------------------------- +// +static char invalid_command[] = "invalid command."; +static char invalid_sample_specified[] = "invalid sample specified."; +static char invalid_stream_specified[] = "invalid stream specified."; +static char invalid_parameter[] = "invalid parameter."; + + +// paste string area ---------------------------------------------------------- +// +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// get an item specified by an index ------------------------------------------ +// +BKGN_Item_s* BKGN_GetItem( int nItem ) +{ + int nIndex = 0; + for ( BKGN_Item_s* scan = BKGN_items_head; scan != NULL; nIndex++ ) { + BKGN_Item_s* next = scan->next; + + if ( nItem == nIndex ) { + return scan; + } + + scan = next; + } + + return NULL; +} + +// Initializes background music files +//RAM replaced mp3 with ogg vorbis files +void AUD_BackGroundPlayer_Init( int voice ) +{ + BKGN_nVoice = voice; + BKGN_nNumItems = 0; + BKGN_nCurrentItem = -1; + BKGN_Started = FALSE; + BKGN_items = NULL; + BKGN_items_head = NULL; + + if ( !AUX_DISABLE_BACKGROUNDPLAYER_ITEM_FILL ) { + + // add music tracks (either from audio cd or as mp3) + for ( int tid = 2; tid < NUM_AUDIO_CD_TRACKS + 2; tid++ ) { + + sprintf( paste_str, "track%d.ogg", tid ); + AUD_BackGroundPlayer_AddStream( paste_str ); + MSGOUT("Loaded %s", paste_str); + + } + + // add game sfx + for ( int sid = 1; sid < NUM_GAMESFX_STREAMS + 1; sid++ ) { + + sprintf( paste_str, "gamesfx%d.ogg", sid ); + AUD_BackGroundPlayer_AddStream( paste_str ); + MSGOUT("Loaded %s", paste_str); + + } + + // new game sfx in pscdata3.dat + AUD_BackGroundPlayer_AddStream( "gamefx10.ogg" ); + MSGOUT("Loaded gamefx10.ogg" ); + AUD_BackGroundPlayer_AddStream( "gamefx11.ogg" ); + MSGOUT("Loaded gamefx11.ogg" ); + + //????RAM not sure what this silence stuff is ???? + // add some silence + AUD_BackGroundPlayer_AddSilence( 15 ); + AUD_BackGroundPlayer_AddSilence( 15 ); + AUD_BackGroundPlayer_AddSilence( 30 ); + } + +} + + +// kill the background sound player ------------------------------------------- +// +void AUD_BackGroundPlayer_Kill() +{ + for ( BKGN_Item_s* scan = BKGN_items_head; scan != NULL; ) { + BKGN_Item_s* next = scan->next; + FREEMEM( scan ); + scan = next; + } + + BKGN_nNumItems = 0; + BKGN_nCurrentItem = -1; + BKGN_Started = FALSE; + BKGN_items_head = NULL; + BKGN_items = NULL; +} + + +// remove an item from the background list ------------------------------------ +// +PRIVATE +BKGN_Item_s* BKGNm_AddItem( int id, const char *filename, dword type ) +{ + // add the background item to the end of the list + + DBGTXT(MSGOUT("Adding Item with id=%i, filename=%s, type=%d\n", id, filename, type);); + BKGN_Item_s* item = (BKGN_Item_s*) ALLOCMEM( sizeof( BKGN_Item_s ) ); + memset( item, 0, sizeof( BKGN_Item_s ) ); + + item->type = type; + + if ( type == BKGN_ITEM_TYPE_STREAM ) { + + item->id = 0; + item->filename = (char *) ALLOCMEM( strlen( filename ) + 1 ); + strcpy( item->filename, filename ); + + } else { + + item->id = id; + item->filename = NULL; + } + + item->groupnext = FALSE; + item->next = NULL; + + if ( BKGN_items_head == NULL ) { + BKGN_items_head = item; + } + + if ( BKGN_items != NULL ) { + BKGN_items->next = item; + } + + BKGN_items = item; + + // increase the number of attached items + BKGN_nNumItems++; + + return item; +} + + +// remove an item from the background list ------------------------------------ +// +PRIVATE +int BKGNm_RemoveItem( dword id, char *filename, dword type ) +{ + int nNumItems = BKGN_nNumItems; + + BKGN_Item_s* prev = NULL; + for ( BKGN_Item_s* scan = BKGN_items_head; scan != NULL; ) { + BKGN_Item_s* next = scan->next; + + if ( scan->type & type ) { + if ( ( scan->id == id ) && ( scan->filename == filename ) ) { + + if ( prev != NULL ) { + prev->next = next; + } else { + BKGN_items_head = next; + } + + if ( scan->filename != NULL ) + FREEMEM( scan->filename ); + + FREEMEM( scan ); + scan = NULL; + + BKGN_nNumItems--; + } + } + + if ( scan != NULL ) + prev = scan; + + scan = next; + } + + return ( nNumItems != BKGN_nNumItems ); +} + + +// add a sample to be played by the background player ------------------------- +// +int AUD_BackGroundPlayer_AddSample( const char *name ) +{ + if ( name != NULL ) { + // fetch the named sample + int sampleid; + sampleinfo_s* pSampleInfo = AUD_FetchSampleByName( name, &sampleid ); + + if ( pSampleInfo != NULL ) { + BKGN_Item_s* item = BKGNm_AddItem( sampleid, NULL, BKGN_ITEM_TYPE_SAMPLE ); + } + return TRUE; + } + + return FALSE; +} + + +// remove a sample from the list of played items ------------------------------ +// +int AUD_BackGroundPlayer_RemoveSample( char *name ) +{ + if ( name != NULL ) { + + // fetch the named sample + int sampleid; + sampleinfo_s* pSampleInfo = AUD_FetchSampleByName( name, &sampleid ); + + // check the whole list and delete the item if needed + if ( pSampleInfo != NULL ) { + + // stop playing if removed item is the currently played + BKGN_Item_s* curitem = BKGN_GetItem( BKGN_nCurrentItem ); + + if ( ( curitem->id == (dword) sampleid ) && ( curitem->type & BKGN_ITEM_TYPE_SAMPLE ) ) { + AUD_BackGroundPlayer_Stop(); + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + } + + // remove the item + int rc = BKGNm_RemoveItem( sampleid, NULL, BKGN_ITEM_TYPE_SAMPLE ); + + // and start playing again + AUD_BackGroundPlayer_Start( FALSE ); + + return rc; + } + } + + return FALSE; +} + + +// add a cd-track to be played by the background player ----------------------- +// +int AUD_BackGroundPlayer_AddTrack( int track ) +{ + BKGN_Item_s* item = BKGNm_AddItem( track, NULL, BKGN_ITEM_TYPE_CDTRACK ); + + return TRUE; +} + + +// remove a cd-track from the list of played items ---------------------------- +// +int AUD_BackGroundPlayer_RemoveTrack( int track ) +{ + // stop playing if removed item is the currently played + BKGN_Item_s* curitem = BKGN_GetItem( BKGN_nCurrentItem ); + + if ( ( curitem->id == (dword) track ) && ( curitem->type & BKGN_ITEM_TYPE_CDTRACK ) ) { + AUD_BackGroundPlayer_Stop(); + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + } + + // remove the item + int rc = BKGNm_RemoveItem( track, NULL, BKGN_ITEM_TYPE_CDTRACK ); + + // and start playing again + AUD_BackGroundPlayer_Start( FALSE ); + + return rc; +} + + + +// add a sample to be played by the background player ------------------------- +// +int AUD_BackGroundPlayer_AddStream( const char *name ) +{ + if ( name != NULL ) { + + BKGN_Item_s* item = BKGNm_AddItem( 0, name, BKGN_ITEM_TYPE_STREAM ); + + return TRUE; + } + + return FALSE; +} + + +// add a silence delay to the background player list -------------------------- +// +int AUD_BackGroundPlayer_AddSilence( int seconds ) +{ + BKGN_Item_s* item = BKGNm_AddItem( seconds, NULL, BKGN_ITEM_TYPE_SILENCE ); + + return TRUE; +} + + +// remove an item from the list ----------------------------------------------- +// +int AUD_BackGroundPlayer_RemoveItem( int item ) +{ + + // stop playing if removed item is the currently played + if ( BKGN_nCurrentItem == item ) { + AUD_BackGroundPlayer_Stop(); + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + } + + // get the item + BKGN_Item_s* curitem = BKGN_GetItem( item ); + + // remove the item + int rc = BKGNm_RemoveItem( curitem->id, curitem->filename, curitem->type ); + + // and start playing again + AUD_BackGroundPlayer_Start( FALSE ); + + return rc; +} + + +// choose a new item to play in the background -------------------------------- +// +INLINE +int BKGNm_ChooseNewItem() +{ + ASSERT( BKGN_nNumItems > 1 ); + + int nNewSample; + + // get current item + BKGN_Item_s* item = BKGN_GetItem( BKGN_nCurrentItem ); + + int group = item ? item->groupnext : FALSE; + if ( BKGN_shuffle && !group ) { + + nNewSample = ( RAND() % BKGN_nNumItems ); + + while ( nNewSample == BKGN_nCurrentItem ) { + nNewSample = ( RAND() % BKGN_nNumItems ); + } + + } else { + + nNewSample = ( BKGN_nCurrentItem + 1 ) % BKGN_nNumItems; + } + + return nNewSample; +} + +// play the next item --------------------------------------------------------- +// +int BKGN_StartNextItem( void* dummy ) +{ + AUD_BackGroundPlayer_Start( TRUE ); + + return TRUE; +} + + +// play a sample -------------------------------------------------------------- +// +PRIVATE +void BKGNm_PlaySample( BKGN_Item_s* item ) +{ + SoundParams_s soundParams; + memset( &soundParams, 0, sizeof( SoundParams_s ) ); + + if ( BKGN_nNumItems == 1 ) { + // if only one sample, then we loop that forever + soundParams.flags = SOUNDPARAMS_LOOP; + soundParams.start = 0; + } + + sampleinfo_s* pSampleInfo = AUD_FetchSampleById( item->id ); + + soundParams.volume = pSampleInfo->volume; + soundParams.flags |= SOUNDPARAMS_VOLUME; + + // retrieve the wave from the sampleinfo + audiowave_t wave = pSampleInfo->samplepointer; + AUDs_PlayVoiceBuffer(BKGN_nVoice, wave, &soundParams); + + // add an event to start the next item, after the sample play has stopped + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_BKGN_SAMPLE_END; + event->callback = BKGN_StartNextItem; + event->callback_params = NULL; + event->refframe_delay = pSampleInfo->size; + event->flags = EVENT_PARAM_ONESHOT | + EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER; + + EVT_AddEvent( event ); +} + + +// play a cd track ------------------------------------------------------------ +// +PRIVATE +void BKGNm_PlayTrack( BKGN_Item_s* item ) +{ + /* + int tracklength = AUDs_CDGetTrackLength( (short)item->id ); + + if ( tracklength != -1 ) { + + AUDs_CDPlay( (short)item->id, -1, -1 ); + + // add an event to start the next item, after the cdtrack play has stopped + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_BKGN_CDTRACK_END; + event->callback = BKGN_StartNextItem; + event->callback_params = NULL; + + event->refframe_delay = FRAME_MEASURE_TIMEBASE * tracklength; + event->flags = EVENT_PARAM_ONESHOT | + EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER; + + EVT_AddEvent( event ); + + } else { + + BKGN_StartNextItem( NULL ); + }*/ + +} + + +// play an audio stream ------------------------------------------------------- +// +PRIVATE +void BKGNm_PlayStream( BKGN_Item_s* item ) +{ + if ( AUDs_PlayAudioStream( item->filename ) ) { + +// MSGOUT( "playing stream %s", item->filename ); + + // specify callback type and flags +// int callbacktype = CBTYPE_STREAM_ENDED | CBFLAG_REMOVE; + + // ensure no dangling callbacks are left around, they might add up +// CALLBACK_DeleteCallback( callbacktype, BKGN_callback_id ); + + // register callback to play next item, after the stream has ended +// BKGN_callback_id = +// CALLBACK_RegisterCallback( callbacktype, BKGN_StartNextItem, (void*) NULL ); + + } else { + +// MSGOUT( "Can't play stream %s", item->filename ); + BKGN_StartNextItem( NULL ); + } +} + +// play an audio stream ------------------------------------------------------- +// +PRIVATE +void BKGNm_PlaySilence( BKGN_Item_s* item ) +{ + // add an event to start the next item, after the silence time has elapsed + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_BKGN_SILENCE_END; + event->callback = BKGN_StartNextItem; + event->callback_params = NULL; + event->refframe_delay = FRAME_MEASURE_TIMEBASE * item->id; + event->flags = EVENT_PARAM_ONESHOT | + EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER; + + EVT_AddEvent( event ); + +} + + +// start playing the background sound by randomly picking one of the samples -- +// +int AUD_BackGroundPlayer_Start( int fromevent ) +{ + if ( DISABLE_MUSIC_FUNCTIONS ) + return FALSE; + + if ( BKGN_nNumItems > 0 ) { + if(fromevent!=42){ + if ( BKGN_Started ) { + AUD_BackGroundPlayer_Stop(); + if ( !fromevent ) { + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + } + } + } + + if ( BKGN_nNumItems == 1 ) { + BKGN_nCurrentItem = 0; + } else { + BKGN_nCurrentItem = BKGNm_ChooseNewItem(); + } + + BKGN_Item_s* item = BKGN_GetItem( BKGN_nCurrentItem ); + + if ( item != NULL ) { + switch ( item->type ) { + + case BKGN_ITEM_TYPE_SAMPLE: + BKGNm_PlaySample( item ); + break; + + case BKGN_ITEM_TYPE_CDTRACK: + BKGNm_PlayTrack( item ); + break; + + case BKGN_ITEM_TYPE_STREAM: + BKGNm_PlayStream( item ); + break; + + case BKGN_ITEM_TYPE_SILENCE: + BKGNm_PlaySilence( item ); + break; + + default: + break; + } + + BKGN_Started = TRUE; + + return TRUE; + } + } + + return FALSE; + +} + + +// ---------------------------------------------------------------------------- +// +extern int FloatingMenuStatusWindowActive(); + + +// maintain background sound playing ------------------------------------------ +// +int AUD_BackGroundPlayer_Maintain() +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) { + // stop playing the background sound if currently playing + if ( BKGN_Started ) { + AUD_BackGroundPlayer_Stop(); + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + } + + return FALSE; + } + + // maintain the background sound + if ( AUX_AUTOSTART_BACKGROUNDPLAYER ) { + + if ( GAME_MODE_ACTIVE() && InGameLoop ) { + + // start background sound, if in game loop, and not yet started + if ( !AUD_BackGroundPlayer_IsPlaying() ) { + AUD_BackGroundPlayer_Start( FALSE ); + return TRUE; + } + + } else if ( !FloatingMenuStatusWindowActive() ) { + + // stop background sound, if out of game loop + if ( AUD_BackGroundPlayer_IsPlaying() ) { + AUD_BackGroundPlayer_Stop(); + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + return TRUE; + } + } + } + + return TRUE; +} + + +// list all samples added to the list of background samples ------------------- +// +void AUD_BackGroundPlayer_List() +{ + int nItem = 0; + char current; + + for ( BKGN_Item_s* scan = BKGN_items_head; scan != NULL; nItem++) { + BKGN_Item_s* next = scan->next; + + if ( ( nItem == BKGN_nCurrentItem ) && BKGN_Started ) { + + current = '*'; + + } else if ( scan->groupnext ) { + + current = '|'; + + } else { + + current = ' '; + } + + switch( scan->type ) { + + case BKGN_ITEM_TYPE_SAMPLE: + { + sampleinfo_s* pSampleInfo = AUD_FetchSampleById( scan->id ); + sprintf( paste_str, "%c [%02d] sample id %u name (%s) volume %u", + current, nItem, (unsigned int)scan->id, + pSampleInfo->name, (unsigned int)pSampleInfo->volume ); + CON_AddLine( paste_str ); + } + + break; + + /*case BKGN_ITEM_TYPE_CDTRACK: + { + int tracklength = AUDs_CDGetTrackLength( (short)scan->id ); + if ( tracklength != -1 ) { + int mins = tracklength / 60; + int secs = tracklength - ( mins * 60 ); + + sprintf( paste_str, "%c [%02d] track %02d length %02d:%02d", current, nItem, + scan->id, mins, secs ); + } else { + + sprintf( paste_str, "%c [%02d] track %02d (no cd available)", current, nItem, + scan->id ); + + } + CON_AddLine( paste_str ); + } + break; + */ + case BKGN_ITEM_TYPE_STREAM: + { + sprintf( paste_str, "%c [%02d] stream %s", current, nItem, scan->filename ); + CON_AddLine( paste_str ); + } + break; + + case BKGN_ITEM_TYPE_SILENCE: + { + sprintf( paste_str, "%c [%02d] silence %u seconds", current, nItem, (unsigned int)scan->id ); + CON_AddLine( paste_str ); + } + break; + + default: + break; + } + + scan = next; + } +} + + +// stop playing the backgroundplayer ------------------------------------------ +// +int AUD_BackGroundPlayer_Stop() +{ + BKGN_Item_s* item = BKGN_GetItem( BKGN_nCurrentItem ); + + if ( item != NULL ) { + switch( item->type ) { + + case BKGN_ITEM_TYPE_SAMPLE: + AUDs_StopVoice( BKGN_nVoice, FALSE ); + break; + + /*case BKGN_ITEM_TYPE_CDTRACK: + AUDs_CDStop(); + break; + */ + case BKGN_ITEM_TYPE_STREAM: + AUDs_StopAudioStream(); + break; + + case BKGN_ITEM_TYPE_SILENCE: + // nothing needs to be done to stop silence + break; + + default: + break; + } + + BKGN_Started = FALSE; + + return TRUE; + } + + return FALSE; +} + + +// check whether a sample is playing ------------------------------------------ +// +int AUD_BackGroundPlayer_IsPlaying() +{ + return BKGN_Started; +} + + +// console command for starting the background sample playing ----------------- +// +PRIVATE +int Cmd_BKGN_START( char *bkgnstr ) +{ + ASSERT( bkgnstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( bkgnstr ); + + // start playing the background sound + AUD_BackGroundPlayer_Start( FALSE ); + + return TRUE; +} + + +// console command for stopping the background sample playing ----------------- +// +PRIVATE +int Cmd_BKGN_STOP( char *bkgnstr ) +{ + ASSERT( bkgnstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( bkgnstr ); + + // stop playing the background sound + AUD_BackGroundPlayer_Stop(); + EVT_RemoveEventType( EVT_TYPE_BKGN_SAMPLE_END ); + EVT_RemoveEventType( EVT_TYPE_BKGN_CDTRACK_END ); + + return TRUE; +} + + +// key table for background sound loading ------------------------------------- +// +static key_value_s bkgn_add_key_value[] = { + + { "sample", NULL, KEYVALFLAG_NONE | KEYVALFLAG_PARENTHESIZE }, + { "track", NULL, KEYVALFLAG_NONE }, + { "stream", NULL, KEYVALFLAG_NONE }, + { "silence", NULL, KEYVALFLAG_NONE }, + + + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_BKGN_ADD_SAMPLE, + KEY_BKGN_ADD_TRACK, + KEY_BKGN_ADD_STREAM, + KEY_BKGN_ADD_SILENCE +}; + + +// console command for adding a background sample ----------------------------- +// +PRIVATE +int Cmd_BKGN_ADD( char *bkgnstr ) +{ + //NOTE: + //CONCOM: + // bkgn_add_command ::= 'bkgn.add' + // itemspec ::= | | + // | + // samplespec ::= 'sample' + // trackspec ::= 'track' + // streamspec ::= 'stream' + // silencespec ::= 'silence' + + ASSERT( bkgnstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( bkgnstr ); + + // scan out all values to bkgn keys + if ( !ScanKeyValuePairs( bkgn_add_key_value, bkgnstr ) ) + return TRUE; + + char *samplename = bkgn_add_key_value[ KEY_BKGN_ADD_SAMPLE ].value; + + char *streamname = bkgn_add_key_value[ KEY_BKGN_ADD_STREAM ].value; + + int track = -1; + + if( bkgn_add_key_value[ KEY_BKGN_ADD_TRACK ].value != NULL ) { + ScanKeyValueInt( &bkgn_add_key_value[ KEY_BKGN_ADD_TRACK ], &track ); + } + + int silenceseconds = -1; + + if( bkgn_add_key_value[ KEY_BKGN_ADD_SILENCE ].value != NULL ) { + ScanKeyValueInt( &bkgn_add_key_value[ KEY_BKGN_ADD_SILENCE ], &silenceseconds ); + + } + + //FIXME: need to split this in bkgn.add.sample and bkgn.add.track + if( track != -1 ) { + + // add a track to the list of background items + if( AUD_BackGroundPlayer_AddTrack( track ) == FALSE ) { + CON_AddLine( invalid_parameter ); + return TRUE; + } + + } else { + + if ( samplename != NULL ) { + + // add a sample to the list of background items + if( AUD_BackGroundPlayer_AddSample( samplename ) == FALSE ) { + CON_AddLine( invalid_sample_specified ); + return TRUE; + } + + } else if ( streamname != NULL ) { + + // add a stream to the list of background items + if( AUD_BackGroundPlayer_AddStream( streamname ) == FALSE ) { + CON_AddLine( invalid_stream_specified ); + return TRUE; + } + + } else if ( silenceseconds != -1 ) { + + // add silence to the list of background items + if( AUD_BackGroundPlayer_AddSilence( silenceseconds ) == FALSE ) { + CON_AddLine( invalid_parameter ); + return TRUE; + } + } + } + + return TRUE; +} + + +// key table for background sound loading ------------------------------------- +// +static key_value_s bkgn_rmv_key_value[] = { + + { "sample", NULL, KEYVALFLAG_NONE | KEYVALFLAG_PARENTHESIZE }, + { "track", NULL, KEYVALFLAG_NONE }, + { "item", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_BKGN_RMV_SAMPLE, + KEY_BKGN_RMV_TRACK, + KEY_BKGN_RMV_ITEM +}; + + +// console command for adding a background sample ----------------------------- +// +PRIVATE +int Cmd_BKGN_REMOVE( char *bkgnstr ) +{ + //NOTE: + //CONCOM: + // bkgn_remove_command ::= 'bkgn.remove' + // itemspec ::= | | + // idspec ::= 'id' + // samplespec ::= 'sample' + // trackspec ::= 'track' + + ASSERT( bkgnstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( bkgnstr ); + + // scan out all values to bkgn keys + if ( !ScanKeyValuePairs( bkgn_rmv_key_value, bkgnstr ) ) + return TRUE; + + char *samplename = bkgn_rmv_key_value[ KEY_BKGN_RMV_SAMPLE ].value; + int track = -1; + + if ( bkgn_rmv_key_value[ KEY_BKGN_RMV_TRACK ].value != NULL ) { + ScanKeyValueInt( &bkgn_rmv_key_value[ KEY_BKGN_RMV_TRACK ], &track); + } + + int item = -1; + if ( bkgn_rmv_key_value[ KEY_BKGN_RMV_ITEM ].value != NULL ) { + ScanKeyValueInt( &bkgn_rmv_key_value[ KEY_BKGN_RMV_ITEM ], &item ); + } + + if ( item != -1 ) { + + // remove a track from the list of background items + if ( !AUD_BackGroundPlayer_RemoveItem( item ) ) { + CON_AddLine( invalid_parameter ); + return TRUE; + + } + + } else { + + //NOTE: + // these are only here for legacy support + + if ( track != -1 ) { + + // remove a track from the list of background items + if ( !AUD_BackGroundPlayer_RemoveTrack( track ) ) { + CON_AddLine( invalid_parameter ); + return TRUE; + } + + } else { + + // remove a sample from the list of background samples + if ( !AUD_BackGroundPlayer_RemoveSample( samplename ) ) { + CON_AddLine( invalid_sample_specified ); + return TRUE; + } + } + + } + + return TRUE; + +} + + +// console command for listing all the background samples --------------------- +// +PRIVATE +int Cmd_BKGN_LIST( char *bkgnstr ) +{ + //NOTE: + //CONCOM: + // bkgn_list_command ::= 'bkgn.list' + + ASSERT( bkgnstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( bkgnstr ); + + // list all added samples + AUD_BackGroundPlayer_List(); + + return TRUE; +} + + +// key table for item grouping ------------------------------------------------ +// +static key_value_s bkgn_group_key_value[] = { + + + { "item", NULL, KEYVALFLAG_MANDATORY }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_BKGN_ITEM +}; + + +// console command for grouping two tracks ------------------------------------ +// +PRIVATE +int Cmd_BKGN_GROUP( char *bkgnstr ) +{ + //NOTE: + //CONCOM: + // bkgn_group_command ::= 'bkgn.group' + // itemspec ::= 'item' + + ASSERT( bkgnstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( bkgnstr ); + + // scan out all values to bkgn keys + if ( !ScanKeyValuePairs( bkgn_group_key_value, bkgnstr ) ) + return TRUE; + + int item = -1; + + if( bkgn_group_key_value[ KEY_BKGN_ITEM ].value != NULL ) { + ScanKeyValueInt( &bkgn_group_key_value[ KEY_BKGN_ITEM ], &item); + } + + // group specified item with next in list + if ( item != -1 ) { + + // get item + BKGN_Item_s* listitem = BKGN_GetItem( item ); + + ASSERT(listitem != NULL); + + if ( listitem->groupnext ) { + + listitem->groupnext = FALSE; + + } else { + + listitem->groupnext = TRUE; + } + + } + + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( AUD_BKGN ) +{ + user_command_s regcom; + memset( ®com, 0, sizeof( user_command_s ) ); + + // register "bkgn.start" command + regcom.command = "bkgn.start"; + regcom.numparams = 0; + regcom.execute = Cmd_BKGN_START; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "bkgn.stop" command + regcom.command = "bkgn.stop"; + regcom.numparams = 0; + regcom.execute = Cmd_BKGN_STOP; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "bkgn.add" command + regcom.command = "bkgn.add"; + regcom.numparams = 1; + regcom.execute = Cmd_BKGN_ADD; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "bkgn.remove" command + regcom.command = "bkgn.remove"; + regcom.numparams = 1; + regcom.execute = Cmd_BKGN_REMOVE; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "bkgn.list" command + regcom.command = "bkgn.list"; + regcom.numparams = 0; + regcom.execute = Cmd_BKGN_LIST; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "bkgn.group" command + regcom.command = "bkgn.group"; + regcom.numparams = 0; + regcom.execute = Cmd_BKGN_GROUP; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "bkgn.shuffle" command + int_command_s intregcom; + memset( &intregcom, 0, sizeof( int_command_s ) ); + + intregcom.command = "bkgn.shuffle"; + intregcom.bmin = 0; + intregcom.bmax = 1; + intregcom.intref = &BKGN_shuffle; + intregcom.realize = NULL; + intregcom.fetch = NULL; + CON_RegisterIntCommand( &intregcom ); +} + diff --git a/src/parsec/aud_comm.cpp b/src/parsec/aud_comm.cpp new file mode 100644 index 0000000..d1b4f49 --- /dev/null +++ b/src/parsec/aud_comm.cpp @@ -0,0 +1,523 @@ +/* + * PARSEC - Audio Console Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:33 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1998 + * Copyright (c) Clemens Beer 1999 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" + +// local module header +#include "aud_comm.h" + +// proprietary module headers +#include "aud_supp.h" +#include "con_arg.h" +#include "con_com.h" +#include "con_int.h" +#include "con_main.h" + + + +// generic string paste area -------------------------------------------------- +// +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// open particular cd drive (for those with more than one drive) -------------- +// +PRIVATE +int CD_Open( char *drivestr ) +{ + ASSERT( drivestr != NULL ); + HANDLE_COMMAND_DOMAIN( drivestr ); + + return TRUE; +} + + +// key table for cd playing --------------------------------------------------- +// +key_value_s cdplay_key_value[] = { + + { "from", NULL, KEYVALFLAG_NONE }, + { "to", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_CDPLAY_FROM, + KEY_CDPLAY_TO +}; + + +// start playing cd audio track ----------------------------------------------- +// +PRIVATE +int CD_Play( char *trackstr ) +{ + ASSERT( trackstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( trackstr ); +/* + // create pointer to list of parameters (first is always the track) + char *tracknumber = strtok( trackstr, " " ); + if ( tracknumber == NULL ) { + CON_AddLine( "track number must be specified." ); + return TRUE; + } + + // check track parameter + char *errpart; + long track = strtol( tracknumber, &errpart, 10 ); + if ( *errpart != 0 ) { + CON_AddLine( "invalid track parameter." ); + return TRUE; + } + + // scan out all values to track keys + if ( !ScanKeyValuePairs( cdplay_key_value, NULL ) ) + return TRUE; + + // defaults + int nFrom = -1; + int nTo = -1; + + if ( ScanKeyValueInt( &cdplay_key_value[ KEY_CDPLAY_FROM ], &nFrom ) < 0 ) { + CON_AddLine( "invalid from parameter." ); + return TRUE; + } + if ( ScanKeyValueInt( &cdplay_key_value[ KEY_CDPLAY_TO ], &nTo ) < 0 ) { + CON_AddLine( "invalid to parameter." ); + return TRUE; + } + + // issue the play command + AUDs_CDPlay( (short)track, nFrom, nTo ); +*/ + return TRUE; +} + + +// stop playing cd audio track ------------------------------------------------ +// +PRIVATE +int CD_Stop( char *params ) +{ + ASSERT( params != NULL ); + USERCOMMAND_NOPARAM( params ); + + + return TRUE; +} + + +// pause playing of cd audio track -------------------------------------------- +// +PRIVATE +int CD_Pause( char *params ) +{ + ASSERT( params != NULL ); + USERCOMMAND_NOPARAM( params ); + + return TRUE; +} + + +// resume playing of cd audio track ------------------------------------------- +// +PRIVATE +int CD_Resume( char *params ) +{ + ASSERT( params != NULL ); + USERCOMMAND_NOPARAM( params ); + + + return TRUE; +} + + +// eject audio cd ------------------------------------------------------------- +// +PRIVATE +int CD_Eject( char *params ) +{ + ASSERT( params != NULL ); + USERCOMMAND_NOPARAM( params ); + + + return TRUE; +} + + +// set cd volume -------------------------------------------------------------- +// +PRIVATE +int CD_Volume( char *volumestr ) +{ + ASSERT( volumestr != NULL ); + HANDLE_COMMAND_DOMAIN( volumestr ); +/* + int nVolume = AUDs_CDGetVolume(); + + char *params; + + if ( (params = QueryIntArgumentEx( volumestr, "%d", &nVolume )) ) { + + // determine if delta modification (++/--) + int delta = 0; + if ( ( params[ 0 ] == '+' ) && ( params[ 1 ] == '+' ) ) + delta = 1; + else if ( ( params[ 0 ] == '-' ) && ( params[ 1 ] == '-' ) ) + delta = -1; + if ( delta != 0 ) + params += 2; + + if ( *params != 0 ) { + char *errpart; + + long sval = strtol( params, &errpart, 10 ); + if ( *errpart == 0 ) { + if ( delta != 0 ) + sval = nVolume + sval * delta; + if ( sval >= AUD_MIN_VOLUME && sval <= AUD_MAX_VOLUME ) { + nVolume = sval; + AUDs_CDSetVolume( nVolume ); + } else { + CON_AddLine( range_error ); + } + } else { + CON_AddLine( invalid_arg ); + } + } else { + CON_AddLine( invalid_arg ); + } + } +*/ + return TRUE; +} + + +// list the contents of the cd ------------------------------------------------ +// +PRIVATE +int CD_List( char *params ) +{ + ASSERT( params != NULL ); + USERCOMMAND_NOPARAM( params ); + + + return TRUE; +} + + +// register cd audio console commands ----------------------------------------- +// +void AUD_RegisterCDCommands() +{ + static int registration_done = FALSE; + + if ( !registration_done ) { + + registration_done = TRUE; + + user_command_s regcom; + memset( ®com, 0, sizeof( user_command_s ) ); + + regcom.command = "cd.open"; + regcom.numparams = 1; + regcom.execute = CD_Open; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.play"; + regcom.numparams = 1; + regcom.execute = CD_Play; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.stop"; + regcom.numparams = 0; + regcom.execute = CD_Stop; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.pause"; + regcom.numparams = 0; + regcom.execute = CD_Pause; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.resume"; + regcom.numparams = 0; + regcom.execute = CD_Resume; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.eject"; + regcom.numparams = 0; + regcom.execute = CD_Eject; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.volume"; + regcom.numparams = 1; + regcom.execute = CD_Volume; + CON_RegisterUserCommand( ®com ); + + regcom.command = "cd.list"; + regcom.numparams = 0; + regcom.execute = CD_List; + CON_RegisterUserCommand( ®com ); + } +} + +// set global volume via console command -------------------------------------- +// +PRIVATE +int Cmd_AUD_VOLUME( char *paramstr ) +{ + //NOTE: + //CONCOM: + // aud_volume_command ::= 'aud.volume' [] + + ASSERT( paramstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( paramstr ); + // create pointer to list of parameters (first is always the name) + char *volume = strtok( paramstr, " " ); + if ( volume == NULL ) { + sprintf( paste_str, "%d", GlobalVolume ); + CON_AddLine( paste_str ); + return TRUE; + } else { + char *errpart; + long lVolume = strtol( volume, &errpart, 10 ); + if ( *errpart != 0 ) { + CON_AddLine( "invalid argument." ); + return TRUE; + } + + if ( ( lVolume < AUD_MIN_VOLUME ) || ( lVolume > AUD_MAX_VOLUME) ) { + CON_AddLine( "range error." ); + return TRUE; + } + + GlobalVolume = lVolume; + } + return TRUE; +} + +// set sample volume (without reloading) via console command ------------------ +// +PRIVATE +int Cmd_AUD_SAMPLEVOLUME( char *paramstr ) +{ + //NOTE: + //CONCOM: + // aud_samplevolume_command ::= 'aud.samplevolume' [] + + ASSERT( paramstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( paramstr ); + + // create pointer to list of parameters (first is always the name) + char *samplename = strtok( paramstr, " " ); + if ( samplename == NULL ) { + CON_AddLine( "name of sample must be specified." ); + return TRUE; + } + + // allow name to be parenthesized to include whitespace + samplename = GetParenthesizedName( samplename ); + if ( samplename == NULL ) { + CON_AddLine( "samplename name invalid." ); + return TRUE; + } + + // lookup the sample + int nSampleID = -1; + sampleinfo_s* pSampleInfo; + + pSampleInfo = AUD_FetchSampleByName( samplename, &nSampleID ); + if( pSampleInfo == NULL ) { + CON_AddLine( "sample not found." ); + return TRUE; + } + + // advance to next token + paramstr = strtok( NULL, " " ); + + int syntaxok = -1; + + // check for specified volume and either set it or print the current volume + long lVolume; + if( paramstr != NULL) { + + char *errpart; + lVolume = strtol( paramstr, &errpart, 10 ); + if ( *errpart != 0 ) { + CON_AddLine( "invalid argument." ); + return TRUE; + } + + syntaxok = 1; + } + + if ( syntaxok ) { + if ( syntaxok == -1 ) { + sprintf( paste_str, "%d", pSampleInfo->volume ); + CON_AddLine( paste_str ); + } else if ( lVolume < AUD_MIN_VOLUME || lVolume > AUD_MAX_VOLUME) { + CON_AddLine( "range error." ); + } else { + if( AUD_SetSampleVolume( nSampleID, lVolume ) == FALSE ) { + CON_AddLine( "setting volume failed." ); + } + } + } + + return TRUE; +} + + +// key table for sample playing --------------------------------------------------- +// +key_value_s sampleplay_key_value[] = { + + { "name", NULL, KEYVALFLAG_PARENTHESIZE }, + { "id", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_SAMPLEPLAY_NAME, + KEY_SAMPLEPLAY_ID +}; + + +// play sample via console command -------------------------------------------- +// +PRIVATE +int Cmd_AUD_PLAYSAMPLE( char *paramstr ) +{ + //NOTE: + //CONCOM: + // aud_playsample_command ::= 'aud.playsample' + // samplespec ::= | + // samplename ::= 'name' + // sampleid ::= 'id' + + ASSERT( paramstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( paramstr ); + + // defaults + char *samplename = NULL; + int nSampleID = -1; + sampleinfo_s* pSampleInfo = NULL; + + // scan out all values to sampleplay keys + if ( !ScanKeyValuePairs( sampleplay_key_value, paramstr ) ) + return TRUE; + + // check whether id or name was specified + if ( sampleplay_key_value[ KEY_SAMPLEPLAY_NAME ].value != NULL ) { + + samplename = sampleplay_key_value[ KEY_SAMPLEPLAY_NAME ].value; + + // lookup the sample + pSampleInfo = AUD_FetchSampleByName( samplename, &nSampleID ); + + } else if ( ScanKeyValueInt( &sampleplay_key_value[ KEY_SAMPLEPLAY_ID ], &nSampleID ) >= 0 ) { + + // lookup the sample + pSampleInfo = AUD_FetchSampleById( nSampleID ); + + } else { + CON_AddLine( "invalid parameter." ); + return TRUE; + } + + if( pSampleInfo == NULL ) { + CON_AddLine( "sample not found." ); + return TRUE; + } + + // get the pointer to the wave data + audiowave_t wave = pSampleInfo->samplepointer; + + // retrieve the volume for this sample + SoundParams_s sound_params; + memset( &sound_params, 0, sizeof( sound_params ) ); + sound_params.volume = ( pSampleInfo->volume == -1 ) ? AUD_MAX_VOLUME : pSampleInfo->volume; + sound_params.flags = SOUNDPARAMS_VOLUME; + + // and play the sample + AUDs_PlayVoiceBuffer( /*STD_VOICE*/2, wave, &sound_params ); + + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( AUD_COMM ) +{ + user_command_s regcom; + memset( ®com, 0, sizeof( user_command_s ) ); + + // register "aud.samplevolume" command + regcom.command = "aud.samplevolume"; + regcom.numparams = 2; + regcom.execute = Cmd_AUD_SAMPLEVOLUME; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "aud.volume" command + regcom.command = "aud.volume"; + regcom.numparams = 1; + regcom.execute = Cmd_AUD_VOLUME; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + + // register "aud.playsample" command + regcom.command = "aud.playsample"; + regcom.numparams = 1; + regcom.execute = Cmd_AUD_PLAYSAMPLE; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); +} + + + diff --git a/src/parsec/aud_game.cpp b/src/parsec/aud_game.cpp new file mode 100644 index 0000000..49ad9ff --- /dev/null +++ b/src/parsec/aud_game.cpp @@ -0,0 +1,2773 @@ +/* + * PARSEC - High Level Audio Functions + * + * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:21 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1997-2000 + * Copyright (c) Clemens Beer 1998-1999 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" +#include "od_class.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" +#include "sys_subh.h" + +// mathematics header +#include "utl_math.h" + +// local module header +#include "aud_game.h" + +// proprietary module headers +#include "aud_supp.h" +#include "con_aux.h" +#include "e_events.h" +#include "obj_game.h" + + +// flags +//#define DISABLE_SELECT_SOUNDS +#define DIST_VOLUME +#define USE_SOUNDSOURCE_LIST +#define REALISTIC_VOLUME_DECREASE + + + +// critical voice numbers ----------------------------------------------------- +// +int SELECT_VOICE = 2; +int STREAM_VOICE_L = 0; +int STREAM_VOICE_R = 1; + + +// default audio file names and paths ----------------------------------------- +// +char menu_stream_name[ PATH_MAX + 1 ] = "menu.ogg"; +char intro_stream_name[ PATH_MAX + 1 ] = "jingle.ogg"; +char console_audio_stream_path[ PATH_MAX + 1 ] = ".\\music\\"; + + +// module local globals ------------------------------------------------------- +// +int g_nLightningsActive = 0; +struct DistVolumeInfo_s* g_pDistVolumeInfo[ NUMCHANNELS ]; // distance volume infos for each channel + + +// global volume -------------------------------------------------------------- +// +int GlobalVolume = AUD_MAX_VOLUME; + + +// ---------------------------------------------------------------------------- +// +#define JIM_COMMENT_VOICE GUN_SELECT_VOICE + + +// sample-channel relations for general ingame sounds ------------------------- +// +static sample_channel_info_s sample_channel_infos[] = { + + { SND_NAME_DROPMINE, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_DAZZLING_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_THIEF_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_AFTERBURNER_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_INVISIBILITY_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_INVUL_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_DUMB_MISSILE_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_GUIDE_MISSILE_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_MINE_COLLECTED, SND_NAME_ENERGYEXTRA, -1, STD_VOICE, TRUE }, + { SND_NAME_ENERGYEXTRA, NULL, -1, ENERGYBOOSTED_VOICE, FALSE }, + { SND_NAME_ENERGYEXTRA, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_DAMAGE_REPAIRED, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_MAXED_OUT, NULL, -1, ENERGYBOOSTED_VOICE, TRUE }, + { SND_NAME_MAXED_OUT, NULL, -1, STD_VOICE, TRUE }, + { SND_NAME_SELECT1, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_SELECT2, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_SHIPDESTROYED, NULL, -1, DESTROYED_VOICE, TRUE }, + { SND_NAME_EXPLOSION, NULL, -1, EXPLOSION_VOICE, TRUE }, + { SND_NAME_LOWENERGY, NULL, -1, LOWENERGY_VOICE, FALSE }, + { SND_NAME_TARGETLOCKED, NULL, -1, LOCKED_VOICE, TRUE }, + { SND_NAME_BUTTONSLIDED, NULL, -1, STD_VOICE, FALSE }, + { SND_NAME_SCV_SLIDE_IN, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SCV_SLIDE_OUT, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_MINEHIT, NULL, -1, EXPLOSION_VOICE, TRUE }, + { SND_NAME_LASER1, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_LASER2, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_LASER3, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_MISSILE1, NULL, -1, MISSILE1_VOICE, TRUE }, + { SND_NAME_MISSILE2, NULL, -1, MISSILE2_VOICE, TRUE }, + { SND_NAME_HELIX, NULL, -1, HELIX_VOICE, TRUE }, + { SND_NAME_TRACKING, NULL, -1, TRACKING_VOICE, TRUE }, + { SND_NAME_TRACKINGBEEP, NULL, -1, TRACKBEEP_VOICE, TRUE }, + { SND_NAME_NEWPLAYER, NULL, -1, NEWPLAYERJOINED_VOICE, TRUE }, + { SND_NAME_OPTIONS_SLIDE_IN, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_OPTIONS_SLIDE_OUT, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER1, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER2, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER3, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER4, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_LASER5, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE1, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE2, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE3, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SELECT_MISSILE4, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_COUNTDOWN1, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN2, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN3, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN4, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_COUNTDOWN5, NULL, -1, COUNTDOWN_VOICE, FALSE }, + { SND_NAME_SWITCH_GUN, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_SWITCH_MISSILE, NULL, -1, SELECT_VOICE, TRUE }, + { SND_NAME_THRUST, NULL, -1, THRUST_VOICE, FALSE }, + { SND_NAME_SLIDETHRUST, NULL, -1, SLIDETHRUST_VOICE, FALSE }, + { SND_NAME_INCOMING, NULL, -1, TRACKBEEP_VOICE, FALSE }, + { SND_NAME_BOOTING, NULL, -1, STD_VOICE, FALSE }, + { SND_NAME_LASERBEAM, NULL, -1, LASER1_VOICE, TRUE }, + { SND_NAME_ENEMYSHIELD_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_ENEMYHULL_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_PLAYERSHIELD_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_PLAYERHULL_HIT, NULL, -1, ENEMY_HIT_VOICE, TRUE }, + { SND_NAME_LOW_SHIELDS, NULL, -1, LOWENERGY_VOICE, TRUE }, + { SND_NAME_ONE_KILL_LEFT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_TWO_KILLS_LEFT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_THREE_KILLS_LEFT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_JIM_COMMENT_AFRAID_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_AFRAID_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_ANGRY_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_ANGRY_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_3, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_WEAPON_4, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_KILLED_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_KILLED_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_EAT_THIS_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_EAT_THIS_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_ENERGY, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_BORED_1, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_JIM_COMMENT_BORED_2, NULL, -1, JIM_COMMENT_VOICE, FALSE }, + { SND_NAME_DECOY_COLLECTED, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_LASER_UPGRADE_COLLECTED, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_PHOTON_CANNON_COLLECTED, NULL, -1, GUN_SELECT_VOICE, TRUE }, + { SND_NAME_SWARM_MISSILES_COLLECTED, NULL, -1, MISS_SELECT_VOICE, TRUE }, + { SND_NAME_SKILL_AMAZING, NULL, -1, JIM_COMMENT_VOICE, TRUE }, + { SND_NAME_SKILL_BRILLIANT, NULL, -1, JIM_COMMENT_VOICE, TRUE }, + { SND_NAME_AFTERBURNER_ACTIVATE, NULL, -1, AFTERBURNER_VOICE, TRUE }, + { SND_NAME_AFTERBURNER_DEACTIVATE, NULL, -1, AFTERBURNER_VOICE, TRUE }, + { SND_NAME_PHOTON_LOADING, NULL, -1, PHOTON_CANNON_VOICE, TRUE }, + { SND_NAME_PHOTON_FIRING, NULL, -1, PHOTON_CANNON_VOICE, TRUE }, + { SND_NAME_SWARM_MISSILES, NULL, -1, SWARM_MISSILE_VOICE, TRUE }, + { SND_NAME_YOU_DID_IT, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_YOU_HAVE_LOST, NULL, -1, ANNOUNCE_VOICE, TRUE }, + { SND_NAME_MINE_DETECTOR, NULL, -1, TRACKBEEP_VOICE, TRUE }, + { SND_NAME_EMP_1, NULL, -1, EMP_VOICE, TRUE }, + { SND_NAME_EMP_2, NULL, -1, EMP_VOICE, TRUE }, + { SND_NAME_EMP_3, NULL, -1, EMP_VOICE, TRUE }, + { SND_NAME_TELEPORTER, NULL, -1, TRACKBEEP_VOICE, TRUE }, + + +}; + +enum { + + SCI_DROPMINE, + SCI_DAZZLING_COLLECTED, + SCI_THIEF_COLLECTED, + SCI_AFTERBURNER_COLLECTED, + SCI_INVISIBILITY_COLLECTED, + SCI_INVUL_COLLECTED, + SCI_DUMB_MISSILE_COLLECTED, + SCI_GUIDE_MISSILE_COLLECTED, + SCI_MINE_COLLECTED, + SCI_ENERGYEXTRA, + SCI_ENERGYEXTRA1, + SCI_DAMAGE_REPAIRED, + SCI_ENERGY_MAXED_OUT, + SCI_MAXED_OUT, + SCI_SELECT1, + SCI_SELECT2, + SCI_SHIPDESTROYED, + SCI_EXPLOSION, + SCI_LOWENERGY, + SCI_TARGETLOCKED, + SCI_BUTTONSLIDED, + SCI_SCV_SLIDE_IN, + SCI_SCV_SLIDE_OUT, + SCI_MINEHIT, + SCI_LASER1, + SCI_LASER2, + SCI_LASER3, + SCI_MISSILE1, + SCI_MISSILE2, + SCI_HELIX, + SCI_TRACKING, + SCI_TRACKINGBEEP, + SCI_NEWPLAYER, + SCI_OPTIONS_SLIDE_IN, + SCI_OPTIONS_SLIDE_OUT, + SCI_SELECT_LASER1, + SCI_SELECT_LASER2, + SCI_SELECT_LASER3, + SCI_SELECT_LASER4, + SCI_SELECT_LASER5, + SCI_SELECT_MISSILE1, + SCI_SELECT_MISSILE2, + SCI_SELECT_MISSILE3, + SCI_SELECT_MISSILE4, + SCI_COUNTDOWN1, + SCI_COUNTDOWN2, + SCI_COUNTDOWN3, + SCI_COUNTDOWN4, + SCI_COUNTDOWN5, + SCI_SWITCH_GUN, + SCI_SWITCH_MISSILE, + SCI_THRUST, + SCI_SLIDETHRUST, + SCI_INCOMING, + SCI_BOOTING, + SCI_LASERBEAM, + SCI_ENEMYSHIELD_HIT, + SCI_ENEMYHULL_HIT, + SCI_PLAYERSHIELD_HIT, + SCI_PLAYERHULL_HIT, + SCI_LOW_SHIELDS, + SCI_ONE_KILL_LEFT, + SCI_TWO_KILLS_LEFT, + SCI_THREE_KILLS_LEFT, + SCI_JIM_COMMENT_AFRAID_1, + SCI_JIM_COMMENT_AFRAID_2, + SCI_JIM_COMMENT_ANGRY_1, + SCI_JIM_COMMENT_ANGRY_2, + SCI_JIM_COMMENT_WEAPON_1, + SCI_JIM_COMMENT_WEAPON_2, + SCI_JIM_COMMENT_WEAPON_3, + SCI_JIM_COMMENT_WEAPON_4, + SCI_JIM_COMMENT_KILLED_1, + SCI_JIM_COMMENT_KILLED_2, + SCI_JIM_COMMENT_EAT_THIS_1, + SCI_JIM_COMMENT_EAT_THIS_2, + SCI_JIM_COMMENT_ENERGY, + SCI_JIM_COMMENT_BORED_1, + SCI_JIM_COMMENT_BORED_2, + SCI_DECOY_COLLECTED, + SCI_LASER_UPGRADE_COLLECTED, + SCI_PHOTON_CANNON_COLLECTED, + SCI_SWARM_MISSILES_COLLECTED, + SCI_SKILL_AMAZING, + SCI_SKILL_BRILLIANT, + SCI_AFTERBURNER_ACTIVATE, + SCI_AFTERBURNER_DEACTIVATE, + SCI_PHOTON_LOADING, + SCI_PHOTON_FIRING, + SCI_SWARM_MISSILES, + SCI_YOU_DID_IT, + SCI_YOU_HAVE_LOST, + SCI_MINE_DETECTOR, + SCI_EMP1, + SCI_EMP2, + SCI_EMP3, + SCI_TELEPORTER, + + SCI_NUM_SAMPLE_CHANNEL_INFOS +}; + +int NumSampleChannelInfos = SCI_NUM_SAMPLE_CHANNEL_INFOS; + + +// refframe delays for playing the specified sound ---------------------------- +// +#define MISSILE_SELECTED_SOUND_DELAY 300 +#define LASER_SELECTED_SOUND_DELAY 300 +#define COUNTDOWN_SOUND_DELAY 300 +#define SHIPDESTROYED_SOUND_DELAY 800 +#define EXPLOSION_SOUND_DELAY 400 +#define KILLSLEFT_SOUND_DELAY 500 +#define THRUST_SOUND_LIFETIME 60 +#define THRUST_FADEOUT_FRAMES 300 +#define DISTANCE_UPDATE_FRAMES ( FRAME_MEASURE_TIMEBASE / 10 ) +#define MAX_DISTANCE_VISIBLE 4096 +#define TARGET_LOCKED_REPEAT_RATE FRAME_MEASURE_TIMEBASE * 3 + + +// module local functions ----------------------------------------------------- +// +PRIVATE int AUDm_GetVolumeDistBased( DistVolumeInfo_s* pDistVolumeInfo ); +PRIVATE int AUDm_AddChannelSoundSource( int nChannel, DistVolumeInfo_s* pDistVolumeInfo ); +PRIVATE int AUDm_RemoveChannelSoundSource( int nChannel, GenObject* originator ); +PRIVATE int AUDm_WalkChannelSoundSources( void *param ); + + +// play sound effect "helix device" ------------------------------------------- +// +PRIVATE +void AUDm_HelixDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DAZZLING_COLLECTED ] ); +} + + +// play sound effect "lightning device" --------------------------------------- +// +PRIVATE +void AUDm_LightningDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_THIEF_COLLECTED ] ); +} + + +// play sound effect "photon device" ------------------------------------------ +// +PRIVATE +void AUDm_PhotonDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PHOTON_CANNON_COLLECTED ] ); +} + + +// play sound effect "afterburner device" ------------------------------------- +// +PRIVATE +void AUDm_AfterBurnerDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_AFTERBURNER_COLLECTED ] ); +} + + +// play sound effect "invisibility device" ------------------------------------ +// +PRIVATE +void AUDm_InvisibilityDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_INVISIBILITY_COLLECTED ] ); +} + + +// play sound effect "invulnerability device" --------------------------------- +// +PRIVATE +void AUDm_InvulnerabilityDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_INVUL_COLLECTED ] ); +} + + +// play sound effect "holo decoy device" -------------------------------------- +// +PRIVATE +void AUDm_HoloDecoyDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DECOY_COLLECTED ] ); +} + + +// play sound effect "laser upgrade" ------------------------------------------ +// +PRIVATE +void AUDm_LaserUpgradeDevice() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_LASER_UPGRADE_COLLECTED ] ); +} + + +// play sound effect "dumb missiles" ------------------------------------------ +// +PRIVATE +void AUDm_DumbMissiles() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DUMB_MISSILE_COLLECTED ] ); +} + + +// play sound effect "guided missiles" ---------------------------------------- +// +PRIVATE +void AUDm_GuidedMissiles() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_GUIDE_MISSILE_COLLECTED ] ); +} + + +// play sound effect "proximity mines" ---------------------------------------- +// +PRIVATE +void AUDm_ProximityMine() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINE_COLLECTED ] ); +} + + +// play sound effect "swarm missiles" ----------------------------------------- +// +PRIVATE +void AUDm_SwarmMissiles() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SWARM_MISSILES_COLLECTED ] ); +} + + +// play sound effect "extra collected" ---------------------------------------- +// +int AUD_ExtraCollected( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch ( type ) { + + // helix cannon + case HELIX_DEVICE: + AUDm_HelixDevice(); + AUD_JimCommenting( JIM_COMMENT_WEAPON ); + break; + + // lightning device + case LIGHTNING_DEVICE: + AUDm_LightningDevice(); + AUD_JimCommenting( JIM_COMMENT_WEAPON ); + break; + + // afterburner device + case AFTERBURNER_DEVICE: + AUDm_AfterBurnerDevice(); + break; + + // cloak (invisibility) device + case INVISIBILITY_DEVICE: + AUDm_InvisibilityDevice(); + break; + + // photon cannon + case PHOTON_DEVICE: + AUDm_PhotonDevice(); + AUD_JimCommenting( JIM_COMMENT_WEAPON ); + break; + + // invulnerability device + case INVULNERABILITY_DEVICE: + AUDm_InvulnerabilityDevice(); + break; + + // holo decoy device + case DECOY_DEVICE: + AUDm_HoloDecoyDevice(); + break; + + // laser upgrade devices + case LASER_UPGRADE_1_DEVICE: + case LASER_UPGRADE_2_DEVICE: + AUDm_LaserUpgradeDevice(); + break; + + // dumb missile package + case MISSILE1TYPE: + AUDm_DumbMissiles(); + break; + + // guide missile package + case MISSILE4TYPE: + AUDm_GuidedMissiles(); + break; + + // swarm missiles package + case MISSILE5TYPE: + AUDm_SwarmMissiles(); + break; + + // proximity mine package + case MINE1TYPE: + AUDm_ProximityMine(); + break; + + default: + break; + } + + return TRUE; +} + + +// play sound effect "energy boosted" ----------------------------------------- +// +int AUD_EnergyBoosted() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENERGYEXTRA ] ); + return TRUE; +} + + +// play sound effect "damage repaired" ---------------------------------------- +// +int AUD_DamageRepaired() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_DAMAGE_REPAIRED ] ); + return TRUE; +} + + +// play sound effect "energy maxed out" --------------------------------------- +// +PRIVATE +void AUDm_EnergyMaxedOut() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENERGY_MAXED_OUT ] ); +} + + +// play sound effect "something maxed out" ------------------------------------ +// +int AUD_MaxedOut( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch( type ) { + + case ENERGY_EXTRA_CLASS: + AUDm_EnergyMaxedOut(); + return TRUE; + + default: + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MAXED_OUT ] ); + break; + } + + return TRUE; +} + + +// play sound effect "select click 1" ----------------------------------------- +// +int AUD_Select1() +{ + +#ifndef DISABLE_SELECT_SOUNDS + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SELECT1 ] ); + +#endif + + return TRUE; +} + + +// play sound effect "select click 2" ----------------------------------------- +// +int AUD_Select2() +{ + +#ifndef DISABLE_SELECT_SOUNDS + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SELECT2 ] ); + +#endif + + return TRUE; +} + + +// schedule event for delayed explosion --------------------------------------- +// +PRIVATE +int AUD_Explosion_Event( void* param ) +{ + int nVolume = (long) param; + ASSERT( ( nVolume >= AUD_MIN_VOLUME ) && ( nVolume <= AUD_MAX_VOLUME ) ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_EXPLOSION ].samplename ); + + if ( fetch_wave != NULL ) { + + // set the volume + fetch_params.volume = nVolume; + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ SCI_EXPLOSION ].channel, + fetch_wave, &fetch_params ); + + return TRUE; + + } else { + + return FALSE; + } +} + + +// play sound effect "ship destroyed" ----------------------------------------- +// +int AUD_ShipDestroyed( GenObject* objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#define DISTANCE_BASED_EXPLOSION + +#ifdef DISTANCE_BASED_EXPLOSION + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_EXPLOSION ].samplename ); + + int nVolume; + + // check whether proper originator is set + if ( objectpo != NULL ) { + + // first we calculate the volume of the explosion based on the distance to the local ship + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 700 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + nVolume = AUDm_GetVolumeDistBased( &DVI ); + + } else { + + nVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? + fetch_params.volume : AUD_MAX_VOLUME; + } + + // now we schedule the event for playing the explosion sample + event_s* eventExplosion = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + eventExplosion->type = EVT_TYPE_SND_EXPLOSION_DELAY; + eventExplosion->callback = (event_callback_t) AUD_Explosion_Event; + eventExplosion->callback_params = (void*) nVolume; + eventExplosion->refframe_delay = EXPLOSION_SOUND_DELAY; + eventExplosion->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( eventExplosion ); + +#else // DISTANCE_BASED_EXPLOSION + + //FIXME: the explosion sample should be played by an event + //AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_EXPLOSION ] ); + + event_s* eventExplosion = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + eventExplosion->type = EVT_TYPE_SND_EXPLOSION_DELAY; + eventExplosion->callback = (event_callback_t) AUD_PlaySampleOnChannel; + eventExplosion->callback_params = &sample_channel_infos[ SCI_EXPLOSION ]; + eventExplosion->refframe_delay = EXPLOSION_SOUND_DELAY; + eventExplosion->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( eventExplosion ); + +#endif // DISTANCE_BASED_EXPLOSION + + event_s* eventShipDestroyed = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + eventShipDestroyed->type = EVT_TYPE_SND_COUNTDOWN; + eventShipDestroyed->callback = (event_callback_t) AUD_PlaySampleOnChannel; + eventShipDestroyed->callback_params = &sample_channel_infos[ SCI_SHIPDESTROYED ]; + eventShipDestroyed->refframe_delay = SHIPDESTROYED_SOUND_DELAY; + eventShipDestroyed->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( eventShipDestroyed ); + + return TRUE; +} + + +// play sound effect "low energy" --------------------------------------------- +// +int AUD_LowEnergy() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_LOWENERGY ] ); + return TRUE; +} + + +// refframe of last target lock ----------------------------------------------- +// +static refframe_t last_target_lock_ref = REFFRAME_INVALID; + + +// play sound effect "target locked" ------------------------------------------ +// +int AUD_Locked() +{ + refframe_t curref = SYSs_GetRefFrameCount(); + + // only play the "target locked" sample when enough time passed between play requests + if ( last_target_lock_ref != REFFRAME_INVALID ) { + if ( ( curref - last_target_lock_ref ) < TARGET_LOCKED_REPEAT_RATE ) { + return TRUE; + } + } + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_TARGETLOCKED ] ); +// MSGOUT( "play target locked at %d ( diff: %d )", curref, curref - last_target_lock_ref ); + last_target_lock_ref = curref; + + return TRUE; +} + + +// play sound effect "menu buttin slided in" ---------------------------------- +// +int AUD_ButtonSlided() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_BUTTONSLIDED ] ); + return TRUE; +} + + +// play sound effect "spacecraft viewer slided in" ---------------------------- +// +int AUD_SpaceCraftViewerIn() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SCV_SLIDE_IN ] ); + return TRUE; +} + + +// play sound effect "spacecraft viewer slided out" ---------------------------- +// +int AUD_SpaceCraftViewerOut() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SCV_SLIDE_OUT ] ); + return TRUE; +} + + +// play sound effect "mine hit" ----------------------------------------------- +// +int AUD_MineCollision() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINEHIT ] ); + return TRUE; +} + + +// play sound effect "player has been killed" --------------------------------- +// +int AUD_PlayerKilled() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINEHIT ] ); + return TRUE; +} + + +// play sound effect "laser fired" -------------------------------------------- +// +int AUD_Laser( GenObject* objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + // determine actual sound + int sci = SCI_LASER1; + dword objtype = objectpo ? objectpo->ObjectType : LASER1TYPE; + + audiowave_t fetchwave = NULL; + SoundParams_s fetchparams; + + switch ( objtype ) { + + case LASER1TYPE: + { + sci = SCI_LASER1; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + + case LASER2TYPE: + { + sci = SCI_LASER2; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + + case LASER3TYPE: + { + sci = SCI_LASER3; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + } + +#ifdef DIST_VOLUME + + if ( fetchwave != NULL ) { + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetchparams.flags & SOUNDPARAMS_VOLUME ) ? fetchparams.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetchparams.volume = AUDm_GetVolumeDistBased( &DVI ); + fetchparams.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, fetchwave, &fetchparams ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play sound effect "missile launched" --------------------------------------- +// +int AUD_Missile( GenObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + // determine actual sound + int sci = SCI_MISSILE1; + dword objtype = objectpo ? objectpo->ObjectType : MISSILE1TYPE; + + audiowave_t fetchwave = NULL; + SoundParams_s fetchparams; + + switch ( objtype ) { + + case MISSILE1TYPE: + { + sci = SCI_MISSILE1; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + + case MISSILE4TYPE: + { + sci = SCI_MISSILE2; + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + fetchwave = fetch_wave; + fetchparams = fetch_params; + } + break; + } + +#ifdef DIST_VOLUME + + if ( fetchwave != NULL ) { + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetchparams.flags & SOUNDPARAMS_VOLUME ) ? fetchparams.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetchparams.volume = AUDm_GetVolumeDistBased( &DVI ); + fetchparams.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, fetchwave, &fetchparams ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play sound effect "drop mine" ---------------------------------------------- +// +int AUD_Mine( GenObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + int sci = SCI_DROPMINE; + +#ifdef DIST_VOLUME + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + AUD_FETCHSAMPLE( sample_channel_infos[ sci ].samplename ); + + if ( fetch_wave != NULL ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetch_params.volume = AUDm_GetVolumeDistBased( &DVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, fetch_wave, &fetch_params ); + + } else { + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play sound effect "energy extra" ------------------------------------------- +// +int AUD_EnergyExtra() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENERGYEXTRA1 ] ); + return TRUE; +} + + +#ifdef DIST_VOLUME + +// calculate the volume based on the distance of two object ------------------- +PRIVATE +int AUDm_GetVolumeDistBased( DistVolumeInfo_s* pDistVolumeInfo ) +{ + // trivial case, when listener is the originator + if ( pDistVolumeInfo->pListener == pDistVolumeInfo->pOriginator ) { + return pDistVolumeInfo->nMaxVolume; + } + + Vector3 posListener, posOriginator; + Vector3 dist; + + ASSERT( pDistVolumeInfo != NULL ); + ASSERT( pDistVolumeInfo->pOriginator != NULL ); + + FetchTVector( pDistVolumeInfo->pListener->ObjPosition, &posListener ); + FetchTVector( pDistVolumeInfo->pOriginator->ObjPosition, &posOriginator ); + + VECSUB( &dist, &posOriginator, &posListener ); + + geomv_t len = VctLenX( &dist ); + geomv_t minvoldist = pDistVolumeInfo->fMinVolumeDist; + geomv_t maxvoldist = pDistVolumeInfo->fMaxVolumeDist; + + // default to max. volume + int nVolume = AUD_MAX_VOLUME; + + // check whether inside of sound sphere + if ( len <= minvoldist ) { + + // check trivial case: inside of max. volume sphere + if ( len <= maxvoldist ) { + nVolume = pDistVolumeInfo->nMaxVolume; + + } else { + +#ifdef REALISTIC_VOLUME_DECREASE + + // NOTE: this formula comes from the QMDX SDK documentation + // Applied_Volume = Volume / ( 1 + ( ( Range / minDistance ) - 1 ) * scale ) + + // calculate fraction inside sound sphere + geomv_t frac = GEOMV_1 + GEOMV_MUL( ( GEOMV_DIV ( len, maxvoldist ) - GEOMV_1 ), FLOAT_TO_GEOMV( pDistVolumeInfo->fRolloffscale ) ); + + nVolume = GEOMV_TO_INT( GEOMV_DIV( INT_TO_GEOMV( pDistVolumeInfo->nMaxVolume ), frac ) ); +#else + + // calculate fraction inside sound sphere + geomv_t frac = GEOMV_DIV( ( len - maxvoldist ), ( minvoldist - maxvoldist ) ); + + // calculate volume + nVolume = pDistVolumeInfo->nMaxVolume - GEOMV_TO_INT( GEOMV_MUL( INT_TO_GEOMV( pDistVolumeInfo->nMaxVolume - pDistVolumeInfo->nMinVolume ), frac ) ); + +#endif // REALISTIC_VOLUME_DECREASE + + } + + } else { + + nVolume = pDistVolumeInfo->nMinVolume; + + } + + return nVolume; +} + + +// callback for setting the distance-based volume of a channel ---------------- +// +PRIVATE +int AUDm_DistVolumeVoice( void* param ) +{ + DistVolumeInfo_s* pDistVolumeInfo = (DistVolumeInfo_s*) param; + ASSERT( pDistVolumeInfo != NULL ); + + // get the volume + int nVolume = AUDm_GetVolumeDistBased( pDistVolumeInfo ); + + // and set it on the channel + AUDs_SetVoiceVolume( pDistVolumeInfo->nChannel, nVolume ); + + // indicate event repetition + return TRUE; +} + + +// add a distance-volume info to list for the specified channel --------------- +// +PRIVATE +int AUDm_AddChannelSoundSource( int nChannel, DistVolumeInfo_s* pDistVolumeInfo ) +{ + ASSERT( ( nChannel >= 0 ) && ( nChannel < NUMCHANNELS ) ); + ASSERT( pDistVolumeInfo != NULL ); + + pDistVolumeInfo->next = g_pDistVolumeInfo[ nChannel ]; + g_pDistVolumeInfo[ nChannel ] = pDistVolumeInfo; + + return TRUE; +} + +// remove a distance-volume info from list for the specified channel ---------- +// +PRIVATE +int AUDm_RemoveChannelSoundSource( int nChannel, GenObject* originator ) +{ + ASSERT( ( nChannel >= 0 ) && ( nChannel < NUMCHANNELS ) ); + + DistVolumeInfo_s* pCurrent = g_pDistVolumeInfo[ nChannel ]; + DistVolumeInfo_s* pLast = NULL; + + for( ; pCurrent != NULL; ) { + + // we assume only one DistVolumeInfo_s per object per channel + if( pCurrent->pOriginator == originator ) { + if ( pLast != NULL ) { + pLast->next = pCurrent->next; + } else { + // remove head element + g_pDistVolumeInfo[ nChannel ] = pCurrent->next; + } + FREEMEM( pCurrent ); + + return TRUE; + } + + pLast = pCurrent; + pCurrent = pCurrent->next; + } + + return FALSE; +} + +// walk all sound sources for a specific channel and set the volume to the loudest one +PRIVATE +int AUDm_WalkChannelSoundSources( void *param ) +{ + int nChannel = (long)param; + + DistVolumeInfo_s* pCurrent = g_pDistVolumeInfo[ nChannel ]; + ASSERT( pCurrent != NULL ); + ASSERT( pCurrent->nChannel == nChannel ); + + int nVolume = 0; + + for( ; pCurrent != NULL; ) { + // get the volume + int nObjectVolume = AUDm_GetVolumeDistBased( pCurrent ); + nVolume = max( nVolume, nObjectVolume ); + + pCurrent = pCurrent->next; + } + + // and set it on the channel + AUDs_SetVoiceVolume( nChannel, nVolume ); + + return TRUE; +} + +#endif // DIST_VOLUME + + +// play sound effect "teleporter" --------------------------------------------- +// +int AUD_Teleporter( GenObject* teleporter ) +{ + // check whether we already play the sample + int stopped; + AUDs_GetVoiceStatus( TRACKBEEP_VOICE, &stopped ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) { + if ( !stopped ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( TRACKBEEP_VOICE, FALSE ); + } + return FALSE; + } + + AUD_FETCHSAMPLE( SND_NAME_TELEPORTER ); + + if ( stopped == 1 ) { + if ( fetch_wave != NULL ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = TRACKBEEP_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 50 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_VOLUME_DISTANCE_TELEPORTER ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = teleporter; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ TRACKBEEP_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( TRACKBEEP_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_TELEPORTER_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) TRACKBEEP_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( TRACKBEEP_VOICE, pDVI ); + + } + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( TRACKBEEP_VOICE, fetch_wave, &fetch_params ); + + } + } + + return TRUE; +} + +// stop "teleporter" effect --------------------------------------------------- +// +int AUD_TeleporterOff( GenObject* teleporter ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUDm_RemoveChannelSoundSource( TRACKBEEP_VOICE, teleporter ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ TRACKBEEP_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_TELEPORTER_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( TRACKBEEP_VOICE, FALSE ); + } + + return TRUE; +} + + +// play sound effect "lightning" ---------------------------------------------- +// +int AUD_Lightning( ShipObject *shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( SND_NAME_LIGHTNING ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + + ASSERT( shippo != NULL ); + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = LIGHTNING_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ LIGHTNING_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( LIGHTNING_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_LIGHTNING_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) LIGHTNING_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( LIGHTNING_VOICE, pDVI ); + + } +#else + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = LIGHTNING_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_LIGHTNING_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + //FIXME: we need to set this to a reasonable value + fetch_params.start = 3648 * 2; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( LIGHTNING_VOICE, fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// stop "lightning" effect ---------------------------------------------------- +// +int AUD_LightningOff( ShipObject* shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( LIGHTNING_VOICE, shippo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ LIGHTNING_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_LIGHTNING_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( LIGHTNING_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_LIGHTNING_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( LIGHTNING_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( LIGHTNING_VOICE, FALSE ); + +#endif // DIST_VOLUME + + return TRUE; +} + + +// play sound effect "helix" -------------------------------------------------- +// +int AUD_Helix( ShipObject *shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_HELIX ].samplename ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + + ASSERT( shippo != NULL ); + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = HELIX_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ HELIX_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( HELIX_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_HELIX_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) HELIX_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( HELIX_VOICE, pDVI ); + + } + +#else // USE_SOUNDSOURCE_LIST + + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = HELIX_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = shippo; + + // immediately set the volume for this channel + AUDm_DistVolumeVoice( pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_HELIX_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( HELIX_VOICE, fetch_wave, &fetch_params ); + + } + + return TRUE; +} + + +// stop sound effect "helix" -------------------------------------------------- +// +int AUD_HelixOff( ShipObject* shippo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( HELIX_VOICE, shippo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ HELIX_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_HELIX_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( HELIX_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_HELIX_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( HELIX_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( HELIX_VOICE, TRUE ); + + +#endif // DIST_VOLUME + + return TRUE; +} + + + +// play sound effect "tracking" ----------------------------------------------- +// +int AUD_Tracking() +{ + //FIXME: + // currently not in use, therefore save time + // by not looking for it. + +// AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_TRACKING ] ); + + return TRUE; +} + + +// play sound effect "tracking beep" ------------------------------------------ +// +int AUD_TrackingBeep() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_TRACKINGBEEP ] ); + return TRUE; +} + + +// play sound effect "player joined" ------------------------------------------ +// +int AUD_NewPlayerJoined() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_NEWPLAYER ] ); + return TRUE; +} + + +// weapons index to weapons mask table ---------------------------------------- +// +//FIXME: gamecode !!! +int index_weapons_mask[ 5 ] = { + + WPMASK_CANNON_LASER, + WPMASK_CANNON_HELIX, + WPMASK_CANNON_LIGHTNING, + WPMASK_CANNON_PHOTON, + WPMASK_DEVICE_EMP, +}; + + +// play sound effect "laser changed" ------------------------------------------ +// +int AUD_SelectLaser( int sellaser ) +{ + ASSERT( ( sellaser >= 0 ) && ( sellaser < 5 ) ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) { + return FALSE; + } + + // check if selected laser is available + if ( OBJ_DeviceAvailable( MyShip, index_weapons_mask[ sellaser ] ) ) { + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_GUN_SELECT; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_SELECT_LASER1 + sellaser ]; + event->refframe_delay = LASER_SELECTED_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // remove any previously issued event + EVT_RemoveEventType( EVT_TYPE_SND_GUN_SELECT ); + } + + // play the gun switching sample + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SWITCH_GUN ] ); + + return TRUE; +} + + +// play sound effect "missile changed" ---------------------------------------- +// +int AUD_SelectMissile( int selmissile ) +{ + ASSERT( ( selmissile >= 0 ) && ( selmissile < 4 ) ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + if ( ( ( selmissile == 0 ) && ( MyShip->NumMissls > 0 ) ) || + ( ( selmissile == 1 ) && ( MyShip->NumHomMissls > 0 ) ) || + ( ( selmissile == 2 ) && ( MyShip->NumMines > 0 ) ) || + ( ( selmissile == 3 ) && ( MyShip->NumPartMissls > 0 ) ) + ) { + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_MISSILE_SELECT; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_SELECT_MISSILE1 + selmissile ]; + event->refframe_delay = MISSILE_SELECTED_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // remove any previously issued event + EVT_RemoveEventType( EVT_TYPE_SND_MISSILE_SELECT ); + } + + // play the gun switching sample + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SWITCH_MISSILE ] ); + + return TRUE; +} + + +// play sound effect for sliding in ------------------------------------------- +// +int AUD_SlideIn( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch( type ) { + + case 0: + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_OPTIONS_SLIDE_IN ] ); + break; + + default: + break; + } + + return TRUE; +} + + +// play sound effect for sliding out ------------------------------------------ +// +int AUD_SlideOut( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + switch( type ) { + + case 0: + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_OPTIONS_SLIDE_OUT ] ); + break; + + default: + break; + } + + return TRUE; +} + + +// play voice sample for missile countdown ------------------------------------ +// +int AUD_Countdown( int num ) +{ + if ( num < 1 || num > 5 ) + return FALSE; + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +// AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_COUNTDOWN1 + num - 1 ] ); + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_COUNTDOWN; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_COUNTDOWN1 + num - 1 ]; + event->refframe_delay = COUNTDOWN_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + return TRUE; +} + + +// struct for handling volume change on a specific channel -------------------- +// +struct ChannelVolumeChange_s { + + int nChannel; + int nVolume; + int nVolumeDelta; +}; + + +// callback function for fading out a specific voice -------------------------- +// +PRIVATE +int AUDm_FadeOutVoice( void* param ) +{ + ChannelVolumeChange_s* pChannelVolumeChange = (ChannelVolumeChange_s*)param; + ASSERT( pChannelVolumeChange != NULL ); + + // decrease the volume + pChannelVolumeChange->nVolume -= abs( pChannelVolumeChange->nVolumeDelta ); + + // and set the volume on the channel + if ( pChannelVolumeChange->nVolume > 0 ) { + + AUDs_SetVoiceVolume( pChannelVolumeChange->nChannel, pChannelVolumeChange->nVolume ); + + // indicate event repetition + return TRUE; + + } else { + + // stop playing the voice + AUDs_StopVoice( pChannelVolumeChange->nChannel, FALSE ); + + // indicate removal of the event + return FALSE; + } +} + + +// start playing the thrust sample -------------------------------------------- +// +int AUD_StartThrust( int type ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + int sci; + dword evttype; + + switch( type ) { + + case THRUST_TYPE_NORMAL: + sci = SCI_THRUST; + evttype = EVT_TYPE_SND_THRUST_FADEOUT; + break; + + case THRUST_TYPE_SLIDE: + sci = SCI_SLIDETHRUST; + evttype = EVT_TYPE_SND_SLIDETHRUST_FADEOUT; + break; + + default: + ASSERT( 0 ); + + } + + // fetch the sample + AUD_FETCHSAMPLE_EX( sample_channel_infos[ sci ].samplename, + sample_channel_infos[ sci ].sampleid ); + + // return, if not available + if ( fetch_pSampleInfo == NULL ) + return FALSE; + + // set the info for fading the volume on a channel + ChannelVolumeChange_s *pCVC = (ChannelVolumeChange_s*) + ALLOCMEM( sizeof ( ChannelVolumeChange_s ) ); + pCVC->nChannel = sample_channel_infos[ sci ].channel; + pCVC->nVolume = fetch_pSampleInfo->volume; + pCVC->nVolumeDelta = pCVC->nVolume / 5; + + // add the event for stopping the Thrust, this removes any previous event + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + event->type = evttype; + event->callback = (event_callback_t) AUDm_FadeOutVoice; + event->callback_params = (void*) pCVC; + event->refframe_delay = THRUST_SOUND_LIFETIME; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + // check whether we already play the sample + int stopped; + AUDs_GetVoiceStatus( sample_channel_infos[ sci ].channel, &stopped ); + + if ( stopped == 0 ) { + // set the volume to max + AUDs_SetVoiceVolume( sample_channel_infos[ sci ].channel, fetch_params.volume ); + return TRUE; + } + + + // enable looping of sample + fetch_params.flags |= SOUNDPARAMS_LOOP; + + if ( fetch_wave != NULL ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci ].channel, + fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// callback function to stop a specific voice --------------------------------- +// +PRIVATE +int AUDm_EventStopVoice( void* param ) +{ + uintptr_t channel = (uintptr_t) param; + AUDs_StopVoice( (int) channel, FALSE ); + + return TRUE; +} + + +// play sample "incoming missile" --------------------------------------------- +// +int AUD_IncomingMissile( int looptime ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_INCOMING ] ); + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_INCOMING_STOP; + event->callback = (event_callback_t) AUDm_EventStopVoice; + event->callback_params = (void *) sample_channel_infos[ SCI_INCOMING ].channel; + event->refframe_delay = looptime; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + return TRUE; +} + + +// flag whether sample "booting" is playing ----------------------------------- +// +static int booting_sample_playing = FALSE; + + +// play sample "booting" ------------------------------------------------------ +// +int AUD_BootOnBoardComputer() +{ + booting_sample_playing = + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_BOOTING ] ); + + return TRUE; +} + + +// make sure "booting" sample is not playing ---------------------------------- +// +int AUD_StopOnBoardComputer() +{ + if ( !booting_sample_playing ) + return FALSE; + + // stop playing the voice + AUDs_StopVoice( sample_channel_infos[ SCI_BOOTING ].channel, FALSE ); + booting_sample_playing = FALSE; + + return TRUE; +} + + +// start sample "laserbeam" --------------------------------------------------- +// +int AUD_StartLaserBeam() +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + // fetch the sample + AUD_FETCHSAMPLE_EX( sample_channel_infos[ SCI_LASERBEAM ].samplename, sample_channel_infos[ SCI_LASERBEAM ].sampleid ); + + // return, if not available + if ( fetch_pSampleInfo == NULL ) + return FALSE; + + // enable looping of sample + fetch_params.flags |= SOUNDPARAMS_LOOP; + + if ( fetch_wave != NULL ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ SCI_LASERBEAM ].channel, fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// stop sample "laserbeam" ---------------------------------------------------- +// +int AUD_StopLaserBeam() +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUDs_StopVoice( sample_channel_infos[ SCI_LASERBEAM ].channel, FALSE ); + + return TRUE; +} + + +// play sound effect "enemy hit" ---------------------------------------------- +// +int AUD_EnemyShieldHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENEMYSHIELD_HIT ] ); + return TRUE; +} + + +// play sound effect "enemyhull hit" ------------------------------------------ +// +int AUD_EnemyHullHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_ENEMYHULL_HIT ] ); + return TRUE; +} + + +// play sound effect "playershield hit" --------------------------------------- +// +int AUD_PlayerShieldHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PLAYERSHIELD_HIT ] ); + return TRUE; +} + + +// play sound effect "playerhull hit" ----------------------------------------- +// +int AUD_PlayerHullHit() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PLAYERHULL_HIT ] ); + return TRUE; +} + + +// play sound effect "mine detector" ------------------------------------------ +// +int AUD_MineDetector() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_MINE_DETECTOR ] ); + return TRUE; +} + + +// play sound effect "low shields" -------------------------------------------- +// +int AUD_LowShields() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_LOW_SHIELDS ] ); + return TRUE; +} + + +// play sound effect "x kills left" ------------------------------------------- +// +int AUD_KillsLeft( int killsleft ) +{ + if ( ( killsleft < 1 ) || ( killsleft > 3 ) ) + return FALSE; + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_KILLSLEFT; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ SCI_ONE_KILL_LEFT + killsleft - 1 ]; + event->refframe_delay = KILLSLEFT_SOUND_DELAY; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + return TRUE; +} + + +// play afterburner activation sample ----------------------------------------- +// +int AUD_ActivateAfterBurner() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_AFTERBURNER_ACTIVATE ] ); + return TRUE; +} + + +// play afterburner deactivation sample --------------------------------------- +// +int AUD_DeactivateAfterBurner() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_AFTERBURNER_DEACTIVATE ] ); + return TRUE; +} + + +// play swarm missiles sample ------------------------------------------------- +// +int AUD_SwarmMissiles( Vertex3 *origin, GenObject *dummyobj ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_SWARM_MISSILES ].samplename ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = SWARM_MISSILE_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = dummyobj; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ SWARM_MISSILE_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( SWARM_MISSILE_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_SWARM_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) SWARM_MISSILE_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( SWARM_MISSILE_VOICE, pDVI ); + + } + +#else // USE_SOUNDSOURCE_LIST + + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = SWARM_MISSILE_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = dummyobj; + + // immediately set the volume for this channel + AUDm_DistVolumeVoice( pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_SWARM_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( SWARM_MISSILE_VOICE, fetch_wave, &fetch_params ); + } + + return TRUE; +} + + +// stop swarm missiles sound effect ------------------------------------------- +// +int AUD_SwarmMissilesOff( GenObject *dummypo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( SWARM_MISSILE_VOICE, dummypo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ SWARM_MISSILE_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_SWARM_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( SWARM_MISSILE_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_SWARM_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( SWARM_MISSILE_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( SWARM_MISSILE_VOICE, TRUE ); + + +#endif // DIST_VOLUME + + return TRUE; +} + + +// play photon cannon loading sound effect ------------------------------------ +// +int AUD_PhotonLoading( ShipObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_PHOTON_LOADING ].samplename ); + + if ( fetch_wave != NULL ) { + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = PHOTON_CANNON_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = objectpo; + + // get the volume for starting the loop + fetch_params.volume = AUDm_GetVolumeDistBased( pDVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + + // check whether there is already a event for this + if ( g_pDistVolumeInfo[ PHOTON_CANNON_VOICE ] == NULL ) { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( PHOTON_CANNON_VOICE, pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_PHOTON_VOLUME; + event->callback = (event_callback_t) AUDm_WalkChannelSoundSources; + event->callback_params = (void*) PHOTON_CANNON_VOICE; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + + } else { + + // add the distance volume info to the list for the lightning channel + AUDm_AddChannelSoundSource( PHOTON_CANNON_VOICE, pDVI ); + + } + +#else // USE_SOUNDSOURCE_LIST + + if ( shippo != MyShip ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s* pDVI = (DistVolumeInfo_s*) ALLOCMEM( sizeof ( DistVolumeInfo_s ) ); + pDVI->nChannel = PHOTON_CANNON_VOICE; + pDVI->nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + pDVI->nMinVolume = AUD_MIN_VOLUME; + pDVI->fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + pDVI->fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + pDVI->fRolloffscale = 1.0f; + pDVI->pListener = MyShip; + pDVI->pOriginator = objectpo; + + // immediately set the volume for this channel + AUDm_DistVolumeVoice( pDVI ); + + // add the event for changing the volume based on the distance + event_s* event = (event_s*) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_PHOTON_VOLUME; + event->callback = (event_callback_t) AUDm_DistVolumeVoice; + event->callback_params = (void*) pDVI; + event->refframe_delay = DISTANCE_UPDATE_FRAMES; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOFREE_CALLBACK | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_LOOP_INDEFINITE | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + +#endif // USE_SOUNDSOURCE_LIST + +#endif //DIST_VOLUME + + fetch_params.flags |= SOUNDPARAMS_LOOP; + fetch_params.start = 0; + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( PHOTON_CANNON_VOICE, fetch_wave, &fetch_params ); + } + + return TRUE; + + +} + + +// stop photon cannon loading sound effect ------------------------------------ +// +int AUD_PhotonLoadingOff( ShipObject *objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + +#ifdef DIST_VOLUME + +#ifdef USE_SOUNDSOURCE_LIST + + AUDm_RemoveChannelSoundSource( PHOTON_CANNON_VOICE, objectpo ); + + // check whether this was the last soundsource playing on the channel + if ( g_pDistVolumeInfo[ PHOTON_CANNON_VOICE ] == NULL ) { + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_PHOTON_VOLUME ); + + // and stop playing, as no other soundsource is available anymore + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( PHOTON_CANNON_VOICE, FALSE ); + } + +#else // USE_SOUNDSOURCE_LIST + + // remove the event for setting the volume + EVT_RemoveEventType( EVT_TYPE_SND_PHOTON_VOLUME ); + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( PHOTON_CANNON_VOICE, FALSE ); + +#endif // USE_SOUNDSOURCE_LIST + +#else // DIST_VOLUME + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_StopVoice( PHOTON_CANNON_VOICE, TRUE ); + + +#endif // DIST_VOLUME + + return TRUE; +} + + +// play photon firing sample -------------------------------------------------- +// +int AUD_PhotonFiring( GenObject* objectpo ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + + AUD_FETCHSAMPLE( sample_channel_infos[ SCI_PHOTON_FIRING ].samplename ); + +#ifdef DIST_VOLUME + + if ( fetch_wave != NULL ) { + + if ( ( objectpo != NULL ) && ( objectpo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = objectpo; + + // get the volume + fetch_params.volume = AUDm_GetVolumeDistBased( &DVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ SCI_PHOTON_FIRING ].channel, fetch_wave, &fetch_params ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_PHOTON_FIRING ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play emp sample ------------------------------------------------------------ +// +int AUD_EmpBlast( ShipObject *shippo, int level ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + int sci_id; + + switch ( level ) { + + case 0: + sci_id = SCI_EMP1; + break; + + case 1: + sci_id = SCI_EMP2; + break; + + case 2: + sci_id = SCI_EMP3; + break; + default: + return FALSE; + } + + AUD_FETCHSAMPLE( sample_channel_infos[ sci_id ].samplename ); + +#ifdef DIST_VOLUME + + if ( fetch_wave != NULL ) { + + if ( ( shippo != NULL ) && ( shippo != MyShip ) ) { + + // set the info for changing the volume based on the distance + DistVolumeInfo_s DVI; + DVI.nMaxVolume = ( fetch_params.flags & SOUNDPARAMS_VOLUME ) ? fetch_params.volume : AUD_MAX_VOLUME; + DVI.nMinVolume = AUD_MIN_VOLUME; + DVI.fMaxVolumeDist = FLOAT_TO_GEOMV( 300 ); // distance for max. volume + DVI.fMinVolumeDist = FLOAT_TO_GEOMV( MAX_DISTANCE_VISIBLE ); // distance for min. volume + DVI.fRolloffscale = 1.0f; + DVI.pListener = MyShip; + DVI.pOriginator = shippo; + + // get the volume + fetch_params.volume = AUDm_GetVolumeDistBased( &DVI ); + fetch_params.flags |= SOUNDPARAMS_VOLUME; + } + + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( sample_channel_infos[ sci_id ].channel, fetch_wave, &fetch_params ); + } + + return TRUE; + +#else + + AUD_PlaySampleOnChannel( &sample_channel_infos[ sci_id ] ); + return TRUE; + +#endif // DIST_VOLUME + +} + + +// play "You Did It" sample --------------------------------------------------- +// +int AUD_YouDidIt() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_YOU_DID_IT ] ); + return TRUE; +} + + +// play "You Have Lost" sample ------------------------------------------------ +// +int AUD_YouHaveLost() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_YOU_HAVE_LOST ] ); + return TRUE; +} + + +// play li comment sample ----------------------------------------------------- +// +int AUD_LiCommenting( int lcid ) +{ + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + //TODO: + + return TRUE; +} + + +// play li comment sample ----------------------------------------------------- +// +int AUD_LiBabbling( int lbid ) +{ + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + //TODO: + + return TRUE; +} + + +// tables for different types of jim comment samples -------------------------- +// +struct jim_comment_type_s { + + int sci; + int probability; + int delay; + int _mksiz16; +}; + +#define NUM_JIM_ANGRY 4 +jim_comment_type_s jim_angry[ NUM_JIM_ANGRY ] = { + { SCI_JIM_COMMENT_AFRAID_1, 25, 0 }, + { SCI_JIM_COMMENT_AFRAID_2, 25, 0 }, + { SCI_JIM_COMMENT_ANGRY_1, 25, 0 }, + { SCI_JIM_COMMENT_ANGRY_2, 25, 0 }, +}; + +#define NUM_JIM_WEAPON 2 +jim_comment_type_s jim_weapon[ NUM_JIM_WEAPON ] = { + { SCI_JIM_COMMENT_WEAPON_1, 50, 1000 }, + { SCI_JIM_COMMENT_WEAPON_2, 50, 1000 }, +}; + +#define NUM_JIM_KILLED 2 +jim_comment_type_s jim_killed[ NUM_JIM_KILLED ] = { + { SCI_JIM_COMMENT_KILLED_1, 50, 300 }, + { SCI_JIM_COMMENT_KILLED_2, 50, 300 }, +}; + +#define NUM_JIM_EATTHIS 2 +jim_comment_type_s jim_eatthis[ NUM_JIM_EATTHIS ] = { + { SCI_JIM_COMMENT_EAT_THIS_1, 50, 600 }, + { SCI_JIM_COMMENT_EAT_THIS_2, 50, 600 }, +}; + +#define NUM_JIM_ENERGY 1 +jim_comment_type_s jim_energy[ NUM_JIM_ENERGY ] = { + { SCI_JIM_COMMENT_ENERGY, 100, 800 }, +}; + +#define NUM_JIM_BORED 2 +jim_comment_type_s jim_bored[ NUM_JIM_BORED ] = { + { SCI_JIM_COMMENT_BORED_1, 50, 0 }, + { SCI_JIM_COMMENT_BORED_2, 50, 0 }, +}; + + +// standard random comment selection function --------------------------------- +// +PRIVATE +jim_comment_type_s *SelectCommentRandomly( jim_comment_type_s *tab, int tablen ) +{ + int selrand = RAND() % 100; + int sumrand = 0; + + for ( int sid = 0; sid < tablen; sid++ ) { + if ( selrand < ( tab[ sid ].probability + sumrand ) ) + return &tab[ sid ]; + sumrand += tab[ sid ].probability; + } + + return NULL; +} + + +// select angry comment depending on local damage ----------------------------- +// +PRIVATE +jim_comment_type_s *SelectCommentAngry( jim_comment_type_s *tab, int tablen ) +{ + ASSERT( NUM_JIM_ANGRY == 4 ); + + int selrand = RAND() % 100; + int threshold = (int)( (float)MyShip->MaxDamage * 0.80f ); + + if ( MyShip->CurDamage < threshold ) { + return ( selrand < 50 ) ? &jim_angry[ 0 ] : &jim_angry[ 1 ]; + } else { + return ( selrand < 50 ) ? &jim_angry[ 2 ] : &jim_angry[ 3 ]; + } +} + + +// table for jim comment samples ---------------------------------------------- +// +struct jim_comment_s { + + int probability; + int numentries; + jim_comment_type_s *table; + jim_comment_type_s *(*selfunc)( jim_comment_type_s *tab, int tablen ); +}; + +jim_comment_s jim_comments[] = { + + { 40, NUM_JIM_ANGRY, jim_angry, SelectCommentAngry }, + { 100, NUM_JIM_WEAPON, jim_weapon, SelectCommentRandomly }, + { 100, NUM_JIM_KILLED, jim_killed, SelectCommentRandomly }, + { 100, NUM_JIM_EATTHIS, jim_eatthis, SelectCommentRandomly }, + { 100, NUM_JIM_ENERGY, jim_energy, SelectCommentRandomly }, + { 60, NUM_JIM_BORED, jim_bored, SelectCommentRandomly }, +}; + +#define NUM_JIM_COMMENTS CALC_NUM_ARRAY_ENTRIES( jim_comments ) + + +// play jim comment sample ---------------------------------------------------- +// +int AUD_JimCommenting( int jcid ) +{ + ASSERT( ( jcid >= 0 ) && ( jcid < JIM_COMMENT_NUM_COMMENTS ) ); + ASSERT( NUM_JIM_COMMENTS == JIM_COMMENT_NUM_COMMENTS ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return TRUE; + + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + // probability that any comment will be played + int decisionrand = RAND() % 100; + if ( decisionrand >= jim_comments[ jcid ].probability ) + return TRUE; + + // let callback select the comment + jim_comment_type_s *dstcom = + (*jim_comments[ jcid ].selfunc)( jim_comments[ jcid ].table, jim_comments[ jcid ].numentries ); + if ( dstcom == NULL ) + return TRUE; + + // play the comment sample + if ( dstcom->delay == 0 ) { + + AUD_PlaySampleOnChannel( &sample_channel_infos[ dstcom->sci ] ); + + } else { + + event_s *event = (event_s *) ALLOCMEM( sizeof ( event_s ) ); + + event->type = EVT_TYPE_SND_COUNTDOWN; + event->callback = (event_callback_t) AUD_PlaySampleOnChannel; + event->callback_params = &sample_channel_infos[ dstcom->sci ]; + event->refframe_delay = dstcom->delay; + event->flags = EVENT_PARAM_AUTOFREE | + EVENT_PARAM_AUTOTRIGGER | + EVENT_PARAM_ONE_PER_TYPE; + EVT_AddEvent( event ); + } + + return TRUE; +} + + +// play jim babble sample ----------------------------------------------------- +// +int AUD_JimBabbling( int jbid ) +{ + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return TRUE; + + if ( !AUX_ENABLE_FUNKY_AUDIO_COMMENTS ) + return TRUE; + + //TODO: + + return TRUE; +} + + +// play "amazing" sample ------------------------------------------------------ +// +int AUD_SkillAmazing() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SKILL_AMAZING ] ); + return TRUE; +} + + +// play "brilliant" sample ---------------------------------------------------- +// +int AUD_SkillBrilliant() +{ + AUD_PlaySampleOnChannel( &sample_channel_infos[ SCI_SKILL_BRILLIANT ] ); + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE_INIT( AUD_GAME ) +{ + +#ifdef USE_SOUNDSOURCE_LIST + + for( int i = 0; i < NUMCHANNELS; i++ ) { + g_pDistVolumeInfo[ i ] = NULL; + } + +#endif // USE_SOUNDSOURCE_LIST + +} + + +// module deregistration function --------------------------------------------- +// +REGISTER_MODULE_KILL( AUD_GAME ) +{ + +#ifdef USE_SOUNDSOURCE_LIST + + // remove all remaining DistVolumeInfos + for ( int i = 0; i < NUMCHANNELS; i++ ) { + DistVolumeInfo_s* pCurrent = g_pDistVolumeInfo[ i ]; + + for( ; pCurrent != NULL; ) { + + DistVolumeInfo_s* pNext = pCurrent->next; + FREEMEM( pCurrent ); + pCurrent = pNext; + + } + g_pDistVolumeInfo[ i ] = NULL; + } + +#endif // USE_SOUNDSOURCE_LIST + +} + + + diff --git a/src/parsec/aud_glob.cpp b/src/parsec/aud_glob.cpp new file mode 100644 index 0000000..56a0393 --- /dev/null +++ b/src/parsec/aud_glob.cpp @@ -0,0 +1,53 @@ +/* + * PARSEC - Global Variables + * + * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:21 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// subsystem headers +#include "aud_defs.h" + +// local module header +#include "aud_glob.h" + + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( AUD_GLOB ) +{ + +} + + + diff --git a/src/parsec/aud_sdlmixer.cpp b/src/parsec/aud_sdlmixer.cpp new file mode 100644 index 0000000..1a36555 --- /dev/null +++ b/src/parsec/aud_sdlmixer.cpp @@ -0,0 +1,603 @@ +/* + * PARSEC - SDL Mixer Functions + * + * $Authors: mrsid $ - $Date: 2004/10/04 12:06:04 $ + * Gold-Reaver $ - $Date: 2004/10/04 12:06:04 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1998-2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include "config.h" +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" + +// local module header +//#include "al_null.h" +#include "snd_api.h" +#include "snd_wav.h" +#include "aud_bkgn.h" +#include "aud_supp.h" +#include "sys_file.h" +#include "sys_path.h" + +#ifdef SYSTEM_TARGET_LINUX + #include + #include +#else + #include + #include +#endif +// flags + +static int snd_init_done = FALSE; +static int in_game_mode = FALSE; +Mix_Chunk *snd_chunks[MAX_SAMPLES]; +Mix_Music *music; +char *tmp_music_buffer = NULL; + +// play the specified sound on channel voice ---------------------------------- +// +int AUDs_PlayVoice( int voice, int sound ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + Mix_PlayChannel(voice, snd_chunks[sound], 0); + + return AUD_RETURN_SUCCESS; +} + + +// play the specified wave on channel voice with normal stereo ---------------- +// +int AUDs_PlayVoiceBuffer( int voice, audiowave_t wave, SoundParams_s *params ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + if (params != NULL) { + + if ( !(params->flags & SOUNDPARAMS_LOOP) ) { + params->numLoops = 0; + } else { + if( !(params->flags & SOUNDPARAMS_LOOP_COUNT)) + params->numLoops = -1; + } + + Mix_PlayChannel(voice, snd_chunks[(long)wave], params->numLoops ); + + } else { + + Mix_PlayChannel(voice, snd_chunks[(long)wave], 0); + return AUD_RETURN_SUCCESS; + + } + + + if ( params->flags & SOUNDPARAMS_VOLUME) { + if (params->volume > 128) + params->volume = 128; + + Mix_Volume(voice, params->volume); + } + + return AUD_RETURN_SUCCESS; +} + + +// set the volume for the specified channel ----------------------------------- +// +int AUDs_SetVoiceVolume( int voice, int volume ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + if (volume > 128) + volume = 128; + + Mix_Volume(voice, volume); + + return AUD_RETURN_SUCCESS; +} + + +// load wave file into memory ------------------------------------------------- +// +PUBLIC int aud_sample_quality = 44100; + +int AUDs_LoadWaveFile( int num ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + ASSERT( ( num >= 0 ) && ( num < MAX_SAMPLES ) ); + + if ( !SoundAvailable ) + return AUD_RETURN_SUCCESS; + + // read the sample and assign the list entry + sample_s* pSample = SND_ReadSample( &SampleInfo[ num ] ); + + SND_ConvertRate( pSample, aud_sample_quality ); + + // numframes are number of individual samples + dword numframes = pSample->samplebytes / pSample->alignment; + + // because SDL_RWFromFP doesn't work cross platform, we need + // to get a little bit kinky + + // set up a buffer for the file + char *tmp_sample_buffer = NULL; + size_t tmp_sample_size = 0; + + // get the size of this sample + tmp_sample_size = SYS_GetFileLength(SampleInfo[num].file); + if (tmp_sample_size <= 0) { + return FALSE; // return on error + } + + // alloc space for the buffer + tmp_sample_buffer = (char *)ALLOCMEM(tmp_sample_size + 1); + + // open the sample file + FILE *wave = SYS_fopen(SampleInfo[num].file, "rb"); + + if (wave == NULL) + return FALSE; + + // read the file into the temp_sample_buffer + int read_rc = SYS_fread((void *)tmp_sample_buffer, 1, tmp_sample_size, wave); + + if (read_rc <= 0) { + MSGOUT("ERROR: Error reading sample %s.", SampleInfo[num].file); + return FALSE; + } + + SDL_RWops *waverwops = SDL_RWFromMem((void *)tmp_sample_buffer, tmp_sample_size); + snd_chunks[num] = Mix_LoadWAV_RW(waverwops, 1); + SYS_fclose(wave); + + FREEMEM( tmp_sample_buffer ); + FREEMEM( pSample->samplebuffer ); + pSample->samplebuffer = NULL; + + +#ifdef SHOW_SAMPLE_LOADING_INFO + + MSGOUT("loaded %-12s to slot %03d: rate: %05d, numch: %02d, type: %s, bytes: %07d", + SampleInfo[ num ].file, num, pSample->samplerate, pSample->numchannels, + ( pSample->samplesize == 8 ) ? "8" : "16" , pSample->samplebytes ); + +#endif // SHOW_SAMPLE_LOADING_INFO + + // store the slot submitted to the play functions + SampleInfo[ num ].samplepointer = (char *)num; + + //CAVEAT: for now we store the number of refframes in size + SampleInfo[ num ].size = FLOAT2INT( (float) FRAME_MEASURE_TIMEBASE * + (float) pSample->samplebytes / (float) ( pSample->samplerate * pSample->alignment ) + 0.5f ); + + FREEMEM( pSample ); + + return AUD_RETURN_SUCCESS; +} + + +// free resources associated with wave file ----------------------------------- +// +int AUDs_FreeWaveFile( int num ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + ASSERT( ( num >= 0 ) && ( num < MAX_SAMPLES ) ); + + if ( !SoundAvailable ) + return AUD_RETURN_SUCCESS; + + Mix_FreeChunk(snd_chunks[num]); + + return AUD_RETURN_SUCCESS; +} + + +// set panning of channel voice ----------------------------------------------- +// +int AUDs_SetVoicePanning( int voice, int panning ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + Mix_SetPanning(voice, panning, panning); + + return AUD_RETURN_SUCCESS; +} + + +// set frequency of channel voice --------------------------------------------- +// +int AUDs_SetVoiceFrequency( int voice, int freq ) +{ + return AUD_RETURN_SUCCESS; +} + + +// get replay status of channel voice ----------------------------------------- +// +int AUDs_GetVoiceStatus( int voice, int *stopped ) +{ + ASSERT( stopped != NULL ); + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + *stopped = !Mix_Playing(voice); + return AUD_RETURN_SUCCESS; +} + + +// stop replay on channel voice ----------------------------------------------- +// +int AUDs_StopVoice( int voice, int finishloop ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + Mix_HaltChannel(voice); + return AUD_RETURN_SUCCESS; +} + + +// speak text string ---------------------------------------------------------- +// +int AUDs_SpeakString( char *speakstr ) +{ + return 0; +} + + +// init sound stuff for game mode --------------------------------------------- +// +int AUDs_OpenGameSound() +{ + + return 1; +} + + +// kill sound stuff for game mode --------------------------------------------- +// +int AUDs_CloseGameSound() +{ + return 1; +} + + +// play specified stream file ------------------------------------------------- +// +int AUDs_PlayAudioStream( char *fname ) +{ + + if (SoundDisabled) + return 1; + + ASSERT(fname!=NULL); + + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + + if (music != NULL) { + Mix_FreeMusic(music); + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + music = NULL; + } + // because SDL_RWFromFP doesn't work cross platform, we need + // to get a little bit kinky + + // set up a buffer for the file + + size_t tmp_music_size = 0; + + // get the size of this sample + tmp_music_size = SYS_GetFileLength(fname); + if (tmp_music_size <= 0) { + return 1; // return on error + } + + // alloc space for the buffer + if (tmp_music_buffer != NULL) { + printf("ERROR: Shouldn't be this far without being cleaned up previously\n"); + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + } + + tmp_music_buffer = (char *)ALLOCMEM(tmp_music_size + 1); + + // open the sample file + FILE *musicfp = SYS_fopen(fname, "rb"); + if (musicfp == NULL) + return 1; + + // read the file into the temp_sample_buffer + int read_rc = SYS_fread((void *)tmp_music_buffer, 1, tmp_music_size, musicfp); + + if(read_rc <= 0) { + MSGOUT("ERROR: Error reading music %s.", fname); + return FALSE; + } + + SDL_RWops * musicrwops = SDL_RWFromMem((void *)tmp_music_buffer, tmp_music_size); + + music = Mix_LoadMUS_RW(musicrwops); + //MSGOUT(" PlayAudioStream() with %s ", fname); + if (music == NULL) { + printf("Mix_LoadMUS(\"%s\"): %s\n", fname, Mix_GetError()); + // this might be a critical error... + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + return 1; + } + + Mix_VolumeMusic(128); + + if (music != NULL) { + Mix_PlayMusic(music, 0); + } + + //Pick up your your toys when you finish + SYS_fclose(musicfp); + + return 1; +} + + +// stop replay of stream file ------------------------------------------------- +// +int AUDs_StopAudioStream() +{ +// Mix_HaltChannel(1); + if (SoundDisabled) + return 1; + + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + + if (music != NULL) { + Mix_FreeMusic(music); + music = NULL; + } + + if (tmp_music_buffer != NULL) { + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + } + + return 1; +} + + +// precache sound effects specified in control file --------------------------- +// +void AUDs_LoadAllSoundEffects() +{ + if (SoundDisabled) + return; + + for (int i = 0; i < NumLoadedSamples; i++) + AUDs_LoadWaveFile(i); +} + + +// free sound effects that have been precached -------------------------------- +// +void AUDs_FreeAllSoundEffects() +{ + if (SoundDisabled) + return; + + for (int sid = 0; sid < NumLoadedSamples; sid++) { + AUDs_FreeWaveFile( sid ); + } +} + + +// init sound stuff for game menu --------------------------------------------- +// +int AUDs_OpenMenuSound() +{ + if (SoundDisabled) + return 1; + + in_game_mode = FALSE; + + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + + AUDs_PlayAudioStream( menu_stream_name ); + + return 1; +} + + +// kill sound stuff for game menu --------------------------------------------- +// +int AUDs_CloseMenuSound() +{ + if (SoundDisabled) + return 1; + + AUDs_StopAudioStream(); + + return 1; +} + + +// init sound stuff for intro animation --------------------------------------- +// +int AUDs_OpenIntroSound() +{ + return 1; +} + + +// kill sound stuff for intro animation --------------------------------------- +// +int AUDs_CloseIntroSound() +{ + return 1; +} + + +// init sound stuff for credits scroller -------------------------------------- +// +int AUDs_OpenCreditsSound() +{ + return 1; +} + + +// kill sound stuff for credits scroller -------------------------------------- +// +int AUDs_CloseCreditsSound() +{ + return 1; +} + + +// set music/stream volume to maximum ----------------------------------------- +// +void AUDs_MaxMusicVolume() +{ + Mix_VolumeMusic(MIX_MAX_VOLUME); +} + + +// set music/stream volume to zero -------------------------------------------- +// +void AUDs_MinMusicVolume() +{ + Mix_VolumeMusic(0); +} + + +// decrease music/stream volume (no continuous fading!) ----------------------- +// +void AUDs_FadeMusicVolume() +{ +} + + +// maintain sound by keeping the output buffer filled ------------------------- +// +void AUDs_MaintainSound() +{ + if ( SoundDisabled ) + return; + + if (!Mix_PlayingMusic() && in_game_mode == FALSE) { + AUD_BackGroundPlayer_Start(FALSE); + in_game_mode = TRUE; + } + + if (!Mix_PlayingMusic()) + AUD_BackGroundPlayer_Start(FALSE); +} + +void AUDs_MusicFinished() +{ + if (in_game_mode) { + // just in case, not that it would matter. + Mix_HaltMusic(); + + if (music != NULL) { + Mix_FreeMusic(music); + music = NULL; + } + + if (tmp_music_buffer != NULL) { + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + } + + // signal the BackGround Player we're ready for the next song. + AUD_BackGroundPlayer_Start(FALSE); + } +} + +// init sound system and sound hardware --------------------------------------- +// +int AUDs_InitSoundSys() +{ + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + MSGOUT("Failed to open audio.\n"); + SoundDisabled = TRUE; + return FALSE; + } + + if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096) == -1) { + MSGOUT("Could not open mixer.\n%s\n",Mix_GetError()); + SoundDisabled = TRUE; + return FALSE; + } + + Mix_AllocateChannels(32); + Mix_Volume(-1, MIX_MAX_VOLUME); + + AUDs_LoadAllSoundEffects(); + AUD_BackGroundPlayer_Init(1); + + //Mix_HookMusicFinished(AUDs_MusicFinished); + + MSGOUT("Sound Init Done\n"); + + snd_init_done = TRUE; + return TRUE; +} + + +// cancel sound system and sound hardware ------------------------------------- +// +int AUDs_KillSoundSys() +{ + AUDs_FreeAllSoundEffects(); + AUD_BackGroundPlayer_Kill(); + + Mix_CloseAudio(); + SDL_Quit(); + + return TRUE; +} + + diff --git a/src/parsec/aud_supp.cpp b/src/parsec/aud_supp.cpp new file mode 100644 index 0000000..7bc2d1a --- /dev/null +++ b/src/parsec/aud_supp.cpp @@ -0,0 +1,150 @@ +/* + * PARSEC - Supporting Audio Code + * + * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:21 $ + * + * Orginally written by: + * Copyright (c) Clemens Beer 1999 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" + +// local module header +#include "aud_supp.h" + +// proprietary module headers +#include "con_aux.h" + + + +// find a sample specified by a name ------------------------------------------ +// +sampleinfo_s* AUD_FetchSampleByName( const char *name, int *id ) +{ + ASSERT( name != NULL ); + ASSERT( id != NULL ); + + // scan entire table of samples + for ( int sampleid = 0; sampleid < NumLoadedSamples; sampleid++ ) { + if ( stricmp( SampleInfo[ sampleid ].name, name ) == 0 ) { + *id = sampleid; + return &SampleInfo [ sampleid ]; + } + } + + // no sample of this name found + return NULL; +} + + +// find a sample specified by its id ------------------------------------------ +// +sampleinfo_s* AUD_FetchSampleById( int id ) +{ + //NOTE: + // this function may be invoked for invalid + // sample ids. in that case NULL will be + // returned. + + // ensure id is valid + if ( ( id < 0 ) || ( id >= NumLoadedSamples ) ) + return (sampleinfo_s*)NULL; + + return &SampleInfo [ id ]; +} + + +// change the volume of the specified sample ---------------------------------- +// +int AUD_SetSampleVolume( int id, int volume ) +{ + //NOTE: + // this function may be invoked for invalid + // sample ids. in that case FALSE will be + // returned. + + if ( ( id >= 0 ) && ( id < NumLoadedSamples ) ) { + + SampleInfo [ id ].volume = volume; + return TRUE; + } + + return FALSE; +} + + +// play a sample on a channel ------------------------------------------------- +// +int AUD_PlaySampleOnChannel( sample_channel_info_s *info ) +{ + ASSERT( info != NULL ); + + if ( DISABLE_AUDIO_FUNCTIONS || AUX_DISABLE_SOUNDEFFECTS ) + return FALSE; + + if ( info->interruptold == FALSE ) { + + // check whether any previous playing has already stopped + int stopped; + AUDs_GetVoiceStatus( info->channel, &stopped ); + + if ( stopped == 0 ) + return FALSE; + } + + if ( info->fallbacksample ) { + + AUD_FETCHSAMPLE_FALLBACK_EX( info->samplename, info->sampleid, + info->fallbacksample ); + if ( fetch_wave != NULL ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( info->channel, fetch_wave, &fetch_params ); + } + + } else { + + AUD_FETCHSAMPLE_EX( info->samplename, info->sampleid ); + + if ( fetch_wave != NULL ) { + AUXDATA_LAST_SOUNDSYS_RETURNCODE = + AUDs_PlayVoiceBuffer( info->channel, fetch_wave, &fetch_params ); + } + } + + return TRUE; +} + + + diff --git a/src/parsec/con_act.cpp b/src/parsec/con_act.cpp new file mode 100644 index 0000000..5010859 --- /dev/null +++ b/src/parsec/con_act.cpp @@ -0,0 +1,3548 @@ +/* + * PARSEC - Action Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1997-2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" +#include "inp_defs.h" +#include "net_defs.h" +#include "sys_defs.h" +#include "vid_defs.h" + +// mathematics header +#include "utl_math.h" + +// local module header +#include "con_act.h" + +// proprietary module headers +#include "con_aux.h" +#include "con_ext.h" +#include "con_int.h" +#include "con_main.h" +#include "e_demo.h" +#include "e_record.h" +#include "e_replay.h" +#include "e_supp.h" +#include "g_camera.h" +#include "g_supp.h" +#include "h_drwhud.h" +#include "h_supp.h" +#include "h_text.h" +#include "m_main.h" +#include "net_game.h" +#ifdef LINKED_PROTOCOL_GAMESERVER + #include "net_serv.h" +#endif // LINKED_PROTOCOL_GAMESERVER +#include "obj_clas.h" +#include "obj_ctrl.h" +#include "obj_xtra.h" +#include "g_sfx.h" +#include "g_wfx.h" +#include "g_emp.h" +#include "sys_file.h" + + +// flags +#define REINIT_LOCAL_SHIP_ON_PREP_RESTORE +#define RECOVER_TARGET_ON_MISSILE_CREATION + + + +// generic string paste area -------------------------------------------------- +// +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// string constants ----------------------------------------------------------- +// +static char invalid_key_id[] = "invalid key identifier."; +static char no_batch_open[] = "no script open."; +static char too_many_pseudos[] = "too many pseudo stars."; +static char no_objcam_allowed[] = "object camera must not be active."; +static char invalid_list[] = "invalid list identifier."; +static char invalid_class[] = "invalid object class identifier."; +static char invalid_action[] = "invalid action."; +static char invalid_id_range[] = "object class id out of range."; +static char no_action_found[] = "no action specified."; +static char non_batch_use[] = "only valid if called from command script."; +static char stream_name_inval[] = "stream name is invalid."; +static char no_stream_started[] = "stream could not be started."; +static char no_stream_stopped[] = "no stream has been stopped."; +static char action_preempted[] = "action command not allowed."; +static char compile_write_err[] = "write error during compilation."; +static char compile_arg_inval[] = "invalid argument found during compilation."; +static char compile_non_comp[] = "non-compilable command found during compilation."; +static char compile_pkt_inval[] = "packet not found during compilation."; +static char only_for_compile[] = "command is only for compilation."; +static char invalid_bin_wait[] = "invalid binary wait argument encountered."; +static char maxplayers_diff[] = "netplayers limit is different from recording."; + + +// pointer to binary parameters ----------------------------------------------- +// +static char *bin_params = NULL; + + +// swap array of int values -------------------------------------------------- +// +INLINE +void SwapParams_int( int num, int32 *source, int32 *dest ) +{ + +#ifdef SYSTEM_BIG_ENDIAN + + for ( int indx = 0; indx < num; indx++ ) { + dest[ indx ] = SWAP_32( source[ indx ] ); + } + +#else + + memcpy( dest, source, sizeof( int32 ) * num ); + +#endif + +} + + +// swap array of hprec_t values ----------------------------------------------- +// +INLINE +void SwapParams_hprec( int num, hprec_t *source, hprec_t *dest ) +{ + +#ifdef SYSTEM_BIG_ENDIAN + + for ( int indx = 0; indx < num; indx++ ) { + + dword *s = (dword *) &source[ indx ]; + dword *d = (dword *) &dest[ indx ]; + + d[ 0 ] = SWAP_32( s[ 1 ] ); + d[ 1 ] = SWAP_32( s[ 0 ] ); + } + +#else + + memcpy( dest, source, sizeof( hprec_t ) * num ); + +#endif + +} + + +// allow no arguments at all instead of all arguments (one-shot flag!!) ------- +// +static int silent_missing_args = FALSE; // all args missing allowed +static int silent_missing_ok; // args were missing, not invalid + + +// check single parameter for action command ---------------------------------- +// +PRIVATE +int AcFetchIntParams( int num, int32 *params ) +{ + ASSERT( num > 0 ); + ASSERT( params != NULL ); + + // assume incorrectly missing arg + silent_missing_ok = FALSE; + + // read parameters binary if possible + if ( bin_params != NULL ) { + SwapParams_int( num, (int32 *) bin_params, params ); + silent_missing_args = FALSE; + return TRUE; + } + + // read specified number of int parameters + while ( num-- ) { + + char *nextparam = strtok( NULL, " " ); + if ( nextparam == NULL ) { + if ( !silent_missing_args ) + CON_AddLine( arg_missing ); + silent_missing_ok = silent_missing_args; + silent_missing_args = FALSE; + return FALSE; + } + + // disabling after first argument enforces either no + // arguments at all, or the entire specified number + // of arguments have to be specified + silent_missing_args = FALSE; + + char *errpart; + int32 ival = (int32) strtol( nextparam, &errpart, int_calc_base ); + + if ( *errpart != 0 ) { + CON_AddLine( invalid_arg ); + return FALSE; + } + + *params++ = ival; + } + + // make sure flag is reset + ASSERT( !silent_missing_args ); + silent_missing_args = FALSE; + + if ( strtok( NULL, " " ) != NULL ) { + CON_AddLine( too_many_args ); + return FALSE; + } + + return TRUE; +} + + +// check float parameters for action command ---------------------------------- +// +PRIVATE +int AcFetchFloatParams( int num, hprec_t *params ) +{ + ASSERT( num > 0 ); + ASSERT( params != NULL ); + + // assume incorrectly missing arg + silent_missing_ok = TRUE; + + // read parameters binary if possible + if ( bin_params != NULL ) { + SwapParams_hprec( num, (hprec_t *) bin_params, params ); + silent_missing_args = FALSE; + return TRUE; + } + + // read specified number of high precision float parameters + while ( num-- ) { + + char *nextparam = strtok( NULL, " " ); + if ( nextparam == NULL ) { + if ( !silent_missing_args ) + CON_AddLine( arg_missing ); + silent_missing_ok = silent_missing_args; + silent_missing_args = FALSE; + return FALSE; + } + + // disabling after first argument enforces either no + // arguments at all, or the entire specified number + // of arguments have to be specified + silent_missing_args = FALSE; + + char *errpart; + hprec_t dval = strtod( nextparam, &errpart ); + + if ( *errpart != 0 ) { + CON_AddLine( invalid_arg ); + return FALSE; + } + + *params++ = dval; + } + + // make sure flag is reset + ASSERT( !silent_missing_args ); + silent_missing_args = FALSE; + + if ( strtok( NULL, " " ) != NULL ) { + CON_AddLine( too_many_args ); + return FALSE; + } + + return TRUE; +} + + +// check string parameter for action command ---------------------------------- +// +PRIVATE +int AcFetchStringParam( char **param, int stripspace ) +{ + ASSERT( param != NULL ); + + // no invalid args + silent_missing_ok = TRUE; + + // read parameter binary if possible + if ( bin_params != NULL ) { + *param = bin_params; + silent_missing_args = FALSE; + return TRUE; + } + + char *nextparam = strtok( NULL, "" ); + if ( nextparam != NULL ) { + + if ( stripspace ) { + + // eat whitespace + char *scan = nextparam; + while ( *scan == ' ' ) + scan++; + + // argument found? + if ( *scan != 0 ) { + + nextparam = scan; + + // cut off trailing whitespace + while ( *scan != 0 ) + scan++; + while ( *--scan == ' ' ) + {} + *( scan + 1 ) = 0; + + } else { + + if ( !silent_missing_args ) + CON_AddLine( arg_missing ); + nextparam = NULL; + } + } + + } else { + + if ( !silent_missing_args ) { + CON_AddLine( arg_missing ); + } + } + + // reset flag + silent_missing_args = FALSE; + + *param = nextparam; + return ( nextparam != NULL ); +} + + +// set automatic pitch (global variable) -------------------------------------- +// +PRIVATE +void AcAutoPitch() +{ + bams_t angle; + if ( AcFetchIntParams( 1, (int32 *) &angle ) ) { + AutomaticPitch = angle; + } +} + + +// set automatic yaw (global variable) ---------------------------------------- +// +PRIVATE +void AcAutoYaw() +{ + bams_t angle; + if ( AcFetchIntParams( 1, (int32 *) &angle ) ) { + AutomaticYaw = angle; + } +} + + +// set automatic roll (global variable) --------------------------------------- +// +PRIVATE +void AcAutoRoll() +{ + bams_t angle; + if ( AcFetchIntParams( 1, (int32 *) &angle ) ) { + AutomaticRoll = angle; + } +} + + +// set automatic horizontal slide (global variable) --------------------------- +// +PRIVATE +void AcAutoSlideX() +{ + hprec_t slideval; + if ( AcFetchFloatParams( 1, &slideval ) ) { + AutomaticSlideHorz = FLOAT_TO_GEOMV( slideval ); + } +} + + +// set automatic vertical slide (global variable) ----------------------------- +// +PRIVATE +void AcAutoSlideY() +{ + hprec_t slideval; + if ( AcFetchFloatParams( 1, &slideval ) ) { + AutomaticSlideVert = FLOAT_TO_GEOMV( slideval ); + } +} + + +// set automatic movement (global variable and MyShip's speed) ---------------- +// +PRIVATE +void AcAutoMove() +{ + fixed_t translation; + if ( AcFetchIntParams( 1, (int32 *) &translation ) ) { + AutomaticMovement = translation; + MyShip->CurSpeed = AutomaticMovement; + } +} + + +// set idle wait count -------------------------------------------------------- +// +PRIVATE +void AcIdleCommand() +{ + int32 waitcount; + if ( AcFetchIntParams( 1, &waitcount ) ) { + + // set duration to wait for + ASSERT( waitcount >= 0 ); + CurActionWait = waitcount; + + // remember for info + demoinfo_lastwait = (refframe_t) waitcount; + + // save level recursion is stalled on + idle_reclevel = rec_depth; + } +} + + +// flag for view camera filter reset after matrix init ------------------------ +// +static int reset_viewcam_filter_on_update = FALSE; + + +// set single column of camera matrix ----------------------------------------- +// +INLINE +void SetCameraColumn( Camera cam, int col, hprec_t *v ) +{ + cam[ 0 ][ col ] = FLOAT_TO_GEOMV( v[ 0 ] ); + cam[ 1 ][ col ] = FLOAT_TO_GEOMV( v[ 1 ] ); + cam[ 2 ][ col ] = FLOAT_TO_GEOMV( v[ 2 ] ); +} + + +// set column #1 of camera matrix --------------------------------------------- +// +PRIVATE +void AcSetCamRotCol1() +{ + hprec_t v[ 3 ]; + if ( AcFetchFloatParams( 3, v ) ) { + SetCameraColumn( ShipViewCamera, 0, v ); + } +} + + +// set column #2 of camera matrix --------------------------------------------- +// +PRIVATE +void AcSetCamRotCol2() +{ + hprec_t v[ 3 ]; + if ( AcFetchFloatParams( 3, v ) ) { + SetCameraColumn( ShipViewCamera, 1, v ); + } +} + + +// set column #3 of camera matrix --------------------------------------------- +// +PRIVATE +void AcSetCamRotCol3() +{ + hprec_t v[ 3 ]; + if ( AcFetchFloatParams( 3, v ) ) { + SetCameraColumn( ShipViewCamera, 2, v ); + } +} + + +// set column #4 of camera matrix --------------------------------------------- +// +PRIVATE +void AcSetCamOrigin() +{ + hprec_t v[ 3 ]; + if ( AcFetchFloatParams( 3, v ) ) { + SetCameraColumn( ShipViewCamera, 3, v ); + } + + // reset view camera smoothing filter if flag set + // (must be used if matrix is updated discontinuously) + if ( reset_viewcam_filter_on_update ) { + CAMERA_ResetFilter(); + reset_viewcam_filter_on_update = FALSE; + } +} + + +// set single column of object position matrix -------------------------------- +// +PRIVATE +void SetObjectMatrxCol( int listid, int col, geomv_t x, geomv_t y, geomv_t z ) +{ + GenObject *obj = NULL; + + switch ( listid ) { + + case PSHIP_LIST_NO: + obj = (GenObject *) FetchFirstShip(); + break; + + case LASER_LIST_NO: + obj = (GenObject *) FetchFirstLaser(); + break; + + case MISSL_LIST_NO: + obj = (GenObject *) FetchFirstMissile(); + break; + + case EXTRA_LIST_NO: + obj = (GenObject *) FetchFirstExtra(); + break; + + case CUSTM_LIST_NO: + obj = (GenObject *) FetchFirstCustom(); + break; + } + + if ( obj != NULL ) { + obj->ObjPosition[ 0 ][ col ] = x; + obj->ObjPosition[ 1 ][ col ] = y; + obj->ObjPosition[ 2 ][ col ] = z; + } else { + CON_AddLine( invalid_list ); + } +} + + +// mapping table for class ids in demo to corresponding current ids ----------- +// +static dword class_map_id_to_name[ MAX_DISTINCT_OBJCLASSES ]; +static dword class_map_old_id; + + +// reset mapping table for class ids ------------------------------------------ +// +void ResetClassMapTable() +{ + // needed to preserve table across multiple + // demos that are played back-to-back + if ( AUX_DISABLE_CLASS_MAP_TABLE_RESET ) + return; + + class_map_old_id = CLASS_ID_INVALID; + + for ( int cid = 0; cid < MAX_DISTINCT_OBJCLASSES; cid++ ) { + class_map_id_to_name[ cid ] = CLASS_ID_INVALID; + } +} + + +// set class id for which class name will be specified ------------------------ +// +void AcClassMapId() +{ + int32 classid; + if ( AcFetchIntParams( 1, &classid ) ) { + if ( (dword)classid < MAX_DISTINCT_OBJCLASSES ) { + class_map_old_id = classid; + } else { + class_map_old_id = CLASS_ID_INVALID; + } + } +} + + +// map class name to current id and set map to corresponding current id ------- +// +void AcClassMapName() +{ + char *classname; + if ( AcFetchStringParam( &classname, ACM_EAT_SPACE( ACM_CLASSMAPNAME ) ) ) { + + dword classid = OBJ_FetchObjectClassId( classname ); + if ( class_map_old_id != CLASS_ID_INVALID ) { + ASSERT( class_map_old_id < MAX_DISTINCT_OBJCLASSES ); + class_map_id_to_name[ class_map_old_id ] = classid; + } + } +} + + +// execute recorded object creation ------------------------------------------- +// +PRIVATE +GenObject *CreateRecordedObject( dword objclass, Xmatrx startmatrx ) +{ + ASSERT( startmatrx != NULL ); + + if ( objclass >= MAX_DISTINCT_OBJCLASSES ) { + CON_AddLine( invalid_id_range ); + return NULL; + } + + // map the recorded class id to the corresponding current class id + if ( class_map_id_to_name[ objclass ] != CLASS_ID_INVALID ) { + objclass = class_map_id_to_name[ objclass ]; + } + + // create object corresponding to original class + GenObject *obj = CreateObject( objclass, startmatrx ); + if ( obj == NULL ) { + + CON_AddLine( invalid_class ); + + } else { + + // play sound effects for certain types + switch ( obj->ObjectType ) { + + case LASER1TYPE: + case LASER2TYPE: + case LASER3TYPE: + AUD_Laser( obj ); + break; + + case MISSILE1TYPE: + case MISSILE4TYPE: + AUD_Missile( obj ); + break; + + case MINE1TYPE: + AUD_Mine( obj ); + break; + } + } + + return obj; +} + + +// for object creation on "ac.objmatrxcol4" instead of "ac.creatobject" ------- +// +static int delayed_object_creation = FALSE; +static dword delayed_object_class; +static dword delayed_object_id; +static dword delayed_object_hostid; +static Xmatrx delayed_object_matrix; + + +// execute delayed creation of recorded object -------------------------------- +// +INLINE +void DelayedObjectCreation() +{ + //NOTE: + // delayed object creation ensures that the objposition matrix + // is already valid on call of OBJ_CTRL::CreateObject(). + + // create object on setting of last matrix column + if ( delayed_object_creation ) { + delayed_object_creation = FALSE; + + GenObject *obj = + CreateRecordedObject( delayed_object_class, delayed_object_matrix ); + + if ( obj != NULL ) { +/* + if ( delayed_object_id != -1 ) { + obj->ObjectNumber = delayed_object_id; + } +*/ + if ( delayed_object_hostid != (dword)-1 ) { + obj->HostObjNumber = delayed_object_hostid; + } + } + } +} + + +// set single column of object position matrix -------------------------------- +// +INLINE +void SetObjMCol( int col ) +{ + hprec_t v[ 4 ]; + if ( AcFetchFloatParams( 4, v ) ) { + + if ( delayed_object_creation ) { + // remember for later use + delayed_object_matrix[ 0 ][ col ] = FLOAT_TO_GEOMV( v[ 1 ] ); + delayed_object_matrix[ 1 ][ col ] = FLOAT_TO_GEOMV( v[ 2 ] ); + delayed_object_matrix[ 2 ][ col ] = FLOAT_TO_GEOMV( v[ 3 ] ); + } else { + // set column directly in object structure + SetObjectMatrxCol( (int) v[ 0 ], col, + FLOAT_TO_GEOMV( v[ 1 ] ), + FLOAT_TO_GEOMV( v[ 2 ] ), + FLOAT_TO_GEOMV( v[ 3 ] ) ); + } + } +} + + +// set single column of object position matrix -------------------------------- +// +PRIVATE +void AcObjectMatrxColumn1() +{ + SetObjMCol( 0 ); +} + +PRIVATE +void AcObjectMatrxColumn2() +{ + SetObjMCol( 1 ); +} + +PRIVATE +void AcObjectMatrxColumn3() +{ + SetObjMCol( 2 ); +} + +PRIVATE +void AcObjectMatrxColumn4() +{ + SetObjMCol( 3 ); + DelayedObjectCreation(); +} + + +// set column #1 of fixed star matrix ----------------------------------------- +// +PRIVATE +void AcSetFixedStarRotCol1() +{ + // dummy for compatibility +} + + +// set column #2 of fixed star matrix ----------------------------------------- +// +PRIVATE +void AcSetFixedStarRotCol2() +{ + // dummy for compatibility +} + + +// set column #3 of fixed star matrix ----------------------------------------- +// +PRIVATE +void AcSetFixedStarRotCol3() +{ + // dummy for compatibility +} + + +// create object of specified class ------------------------------------------- +// +PRIVATE +void AcCreateObject() +{ + ASSERT( !delayed_object_creation ); + + int32 objclass; + if ( AcFetchIntParams( 1, &objclass ) ) { + + if ( AUX_NO_DELAYED_CREATE_OBJECT_REPLAY ) { + + // create on "ac.creatobject" + Xmatrx im; + MakeIdMatrx( im ); + CreateRecordedObject( objclass, im ); + + } else { + + // create later on "ac.objmatrxcol4" + delayed_object_creation = TRUE; + delayed_object_class = objclass; + delayed_object_id = (dword)-1; // not yet set + delayed_object_hostid = (dword)-1; // not yet set + } + } +} + + +// delete all objects from specified object list ------------------------------ +// +PRIVATE +void AcDestroyObjectList() +{ + if ( ObjCameraActive ) { + CON_AddLine( no_objcam_allowed ); + return; + } + + int32 listid; + if ( AcFetchIntParams( 1, &listid ) ) { + + switch ( listid ) { + + case PSHIP_LIST_NO: + FreeObjList( PShipObjects ); + break; + + case LASER_LIST_NO: + FreeObjList( LaserObjects ); + break; + + case MISSL_LIST_NO: + FreeObjList( MisslObjects ); + break; + + case EXTRA_LIST_NO: + FreeObjList( ExtraObjects ); + break; + + case CUSTM_LIST_NO: + FreeObjList( CustmObjects ); + break; + + default: + CON_AddLine( invalid_list ); + } + } +} + + +// write line 0 in small letters ---------------------------------------------- +// +PRIVATE +void AcWriteSmall() +{ + char *nextparam; + if ( AcFetchStringParam( &nextparam, ACM_EAT_SPACE( ACM_WRITESMALL ) ) ) { +// HUD_SetDemoText( 0, nextparam ); + } +} + + +// write line 1 in capital letters -------------------------------------------- +// +PRIVATE +void AcWriteBig() +{ + char *nextparam; + if ( AcFetchStringParam( &nextparam, ACM_EAT_SPACE( ACM_WRITEBIG1 ) ) ) { +// HUD_SetDemoText( 1, nextparam ); + } +} + + +// write line 2 in capital letters -------------------------------------------- +// +PRIVATE +void AcWriteBig2() +{ + char *nextparam; + if ( AcFetchStringParam( &nextparam, ACM_EAT_SPACE( ACM_WRITEBIG2 ) ) ) { +// HUD_SetDemoText( 2, nextparam ); + } +} + + +// write line 3 in capital letters -------------------------------------------- +// +PRIVATE +void AcWriteBig3() +{ + char *nextparam; + if ( AcFetchStringParam( &nextparam, ACM_EAT_SPACE( ACM_WRITEBIG3 ) ) ) { +// HUD_SetDemoText( 3, nextparam ); + } +} + + +// scroll demo text out ------------------------------------------------------- +// +PRIVATE +void AcClearText() +{ +// HUD_ClearDemoText(); +} + + +// set global maximum number of remote players (NET_GLOB::CurMaxPlayers) ------ +// +PRIVATE +void AcRemoteMaxPlayers() +{ + if ( !NetConnected ) { + CON_AddLine( "AcRemoteMaxPlayers(): no net." ); + return; + } + + int32 maxnumplayers; + if ( AcFetchIntParams( 1, &maxnumplayers ) ) { + + if ( NetConnected == NETWORK_GAME_SIMULATED ) { + // simply set it + CurMaxPlayers = maxnumplayers; + } else { + // can't set it, display warning if different + if ( CurMaxPlayers != maxnumplayers ) { + CON_AddLine( maxplayers_diff ); + } + } + } +} + + +// remember id of remote player whose state was set last ---------------------- +// +static int last_remote_playerid = 0; + + +// create remote player with specified state ---------------------------------- +// +PRIVATE +void AcRemotePlayer() +{ + if ( !NetConnected ) { + CON_AddLine( "AcRemotePlayer(): no net." ); + return; + } + + //NOTE: + // if this is invoked specifying the local player, the + // local id may change. this has to happen in order to + // restore a consistent state with respect to the state + // during recording. the state of the local player will + // also be used to determine whether to activate or + // deactivate entry-mode automatically. + + int32 params[ 4 ]; + if ( AcFetchIntParams( 4, params ) ) { + + // remember id for AcRemoteMatrix(), AcRemoteName(), + // and AcRemoteWeaponsActive() + last_remote_playerid = params[ 0 ]; + + // init state except matrix and name + NET_SetRemotePlayerState( params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ] ); + } +} + + +// set remote player matrix --------------------------------------------------- +// +PRIVATE +void AcRemoteMatrix() +{ + if ( !NetConnected ) { + CON_AddLine( "AcRemoteMatrix(): no net." ); + return; + } + + hprec_t v[ 12 ]; + if ( AcFetchFloatParams( 12, v ) ) { + + Xmatrx matrix; + matrix[ 0 ][ 0 ] = FLOAT_TO_GEOMV( v[ 0 ] ); + matrix[ 0 ][ 1 ] = FLOAT_TO_GEOMV( v[ 1 ] ); + matrix[ 0 ][ 2 ] = FLOAT_TO_GEOMV( v[ 2 ] ); + matrix[ 0 ][ 3 ] = FLOAT_TO_GEOMV( v[ 3 ] ); + matrix[ 1 ][ 0 ] = FLOAT_TO_GEOMV( v[ 4 ] ); + matrix[ 1 ][ 1 ] = FLOAT_TO_GEOMV( v[ 5 ] ); + matrix[ 1 ][ 2 ] = FLOAT_TO_GEOMV( v[ 6 ] ); + matrix[ 1 ][ 3 ] = FLOAT_TO_GEOMV( v[ 7 ] ); + matrix[ 2 ][ 0 ] = FLOAT_TO_GEOMV( v[ 8 ] ); + matrix[ 2 ][ 1 ] = FLOAT_TO_GEOMV( v[ 9 ] ); + matrix[ 2 ][ 2 ] = FLOAT_TO_GEOMV( v[ 10 ] ); + matrix[ 2 ][ 3 ] = FLOAT_TO_GEOMV( v[ 11 ] ); + + // set matrix of remote player (using id set by AcRemotePlayer()) + NET_SetRemotePlayerMatrix( last_remote_playerid, matrix ); + + // for local player additionally set view camera + if ( Player_ShipId[ last_remote_playerid ] == SHIPID_LOCALPLAYER ) { + + ASSERT( LocalPlayerId == last_remote_playerid ); + ASSERT( Player_Ship[ last_remote_playerid ] == MyShip ); + + ObjCamOff(); + CalcOrthoInverse( MyShip->ObjPosition, DestXmatrx ); + memcpy( ShipViewCamera, DestXmatrx, sizeof( Camera ) ); + CAMERA_ResetFilter(); + } + } +} + + +// set remote player weapons state -------------------------------------------- +// +PRIVATE +void AcRemoteWeaponsActive() +{ + //NOTE: + // if new duration weapons are added this function + // should be updated. + + if ( !NetConnected ) { + CON_AddLine( "AcRemoteWeaponsActive(): no net." ); + return; + } + + int32 weaponsactive; + if ( AcFetchIntParams( 1, &weaponsactive ) ) { + + ASSERT( Player_Ship[ last_remote_playerid ] != NULL ); + ASSERT( Player_ShipId[ last_remote_playerid ] != SHIPID_LOCALPLAYER ); + + ShipObject *shippo = (ShipObject *) Player_Ship[ last_remote_playerid ]; + ASSERT( shippo != NULL ); + ASSERT( shippo != MyShip ); + + // check for lightning state change + dword oldstate = shippo->WeaponsActive & WPMASK_CANNON_LIGHTNING; + dword newstate = weaponsactive & WPMASK_CANNON_LIGHTNING; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_RemoteActivateLightning( last_remote_playerid ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_RemoteDeactivateLightning( last_remote_playerid ); + } + + // check for helix state change + oldstate = shippo->WeaponsActive & WPMASK_CANNON_HELIX; + newstate = weaponsactive & WPMASK_CANNON_HELIX; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_RemoteActivateHelix( last_remote_playerid ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_RemoteDeactivateHelix( last_remote_playerid ); + } + + // check for photon state change + oldstate = shippo->WeaponsActive & WPMASK_CANNON_PHOTON; + newstate = weaponsactive & WPMASK_CANNON_PHOTON; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_RemoteActivatePhoton( last_remote_playerid ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_RemoteDeactivatePhoton( last_remote_playerid ); + } + + // check for emp state change + oldstate = shippo->WeaponsActive & WPMASK_DEVICE_EMP; + newstate = weaponsactive & WPMASK_DEVICE_EMP; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_RemoteActivateEmp( last_remote_playerid ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_RemoteDeactivateEmp( last_remote_playerid ); + } + + // fallback for unknown duration weapons + // (simply set/reset activation bits) + dword unknownmask = 0xffffffff; + unknownmask &= ~WPMASK_CANNON_LIGHTNING; + unknownmask &= ~WPMASK_CANNON_HELIX; + unknownmask &= ~WPMASK_CANNON_PHOTON; + unknownmask &= ~WPMASK_DEVICE_EMP; + shippo->WeaponsActive &= ~unknownmask; + shippo->WeaponsActive |= weaponsactive & unknownmask; + } +} + + +// should a join be performed on the next "ac.remotename" ? ------------------- +// +static int join_on_setname = FALSE; + + +// perform recorded join ------------------------------------------------------ +// +PRIVATE +void PerformRecordedJoin() +{ + if ( !NetJoined ) { + HideFloatingMenu(); + NETs_Join(); + EntryMode = FALSE; + InFloatingMenu = FALSE; + } + + ASSERT( EntryMode == FALSE ); + ASSERT( InFloatingMenu == FALSE ); +} + + +// set remote player name ----------------------------------------------------- +// +PRIVATE +void AcRemoteName() +{ + if ( !NetConnected ) { + CON_AddLine( "AcRemoteName(): no net." ); + return; + } + + char *nextparam; + if ( AcFetchStringParam( &nextparam, ACM_EAT_SPACE( ACM_REMOTENAME ) ) ) { + + // set name of remote player (using id set by AcRemotePlayer()) + NET_SetRemotePlayerName( last_remote_playerid, nextparam ); + } + + // perform delayed join + if ( join_on_setname ) { + join_on_setname = FALSE; + PerformRecordedJoin(); + } +} + + +// perform join for local player ---------------------------------------------- +// +PRIVATE +void AcRemoteJoin() +{ + ASSERT( !join_on_setname ); + + if ( !NetConnected ) { + CON_AddLine( "AcRemoteJoin(): no net." ); + return; + } + + int32 params[ 3 ]; + if ( AcFetchIntParams( 3, params ) ) { + + ASSERT( LocalPlayerId == params[ 0 ] ); + + //NOTE: + // player position has to be set by following "ac.remotematrix". + + // remember id for AcRemoteMatrix(), AcRemoteName(), + // and AcRemoteWeaponsActive() + last_remote_playerid = params[ 0 ]; + + // prepare local ship for join + InitJoinReplay(); + + if ( AUX_NO_DELAYED_JOIN_REPLAY ) { + PerformRecordedJoin(); + } else { + join_on_setname = TRUE; + } + } +} + + +// perform unjoin for local player -------------------------------------------- +// +PRIVATE +void AcRemoteUnjoin() +{ + ASSERT( !join_on_setname ); + + if ( !NetConnected ) { + CON_AddLine( "AcRemoteUnjoin(): no net." ); + return; + } + + int32 params[ 3 ]; + if ( AcFetchIntParams( 3, params ) ) { + + ASSERT( LocalPlayerId == params[ 0 ] ); + + // set flags if not already unjoined + if ( NetJoined ) { + ExitGameLoop = 2; + if ( params[ 1 ] == SHIP_DOWNED ) { + ShipDowned = TRUE; + AUD_PlayerKilled(); + } else { + ShipDowned = FALSE; + } + } + } +} + + +// clear remnants of demo replay ---------------------------------------------- +// +PRIVATE +void AcClearDemo() +{ + //NOTE: + // this function has to be used after a demo containing network packets + // has been replayed (and ended) to restore/ensure a proper game state. + + //NOTE: + // if the network mode is not active or the net simulation has already + // been stopped (e.g., the demo has finished) the network state will + // be left untouched (i.e., not reset!). + + ASSERT( !join_on_setname ); + + // specify optional argument flag + silent_missing_args = TRUE; + + // default is stop demo if running + int32 stopflag = 1; + AcFetchIntParams( 1, &stopflag ); + + //NOTE: + // ( silent_missing_ok == FALSE ) is alright here, since an error + // message will already have been displayed and we only wanted to + // override a default value anyway. + + // perform actual clear + DEMO_ClearDemo( stopflag ); +} + + +// start playback of recorded remote packet ----------------------------------- +// +PRIVATE +void AcPlayRemotePacket() +{ + int32 params[ 2 ]; + if ( AcFetchIntParams( 2, params ) ) { + + REC_PlayRemotePacket( params[ 0 ], params[ 1 ] ); + } +} + + +// replay recorded server message --------------------------------------------- +// +PRIVATE +void AcPlayServerMessage() +{ + char *nextparam; + if ( AcFetchStringParam( &nextparam, ACM_EAT_SPACE( ACM_SERVERMSG ) ) ) { + +#ifdef LINKED_PROTOCOL_GAMESERVER + if ( NET_ProtocolGMSV() ) { + NET_ServerParseMessage( nextparam ); + } else { + DBGTXT( MSGOUT( "AcPlayServerMessage(): in non GMSV mode !" ); ); + } +#endif // LINKED_PROTOCOL_GAMESERVER + + } +} + + +// display message in console ------------------------------------------------- +// +PRIVATE +void AcWriteConsoleText() +{ + char *msgtext; + if ( AcFetchStringParam( &msgtext, ACM_EAT_SPACE( ACM_WRITECONSOLETEXT ) ) ) { + + CON_AddLine( msgtext ); + } +} + + +// display message in message area -------------------------------------------- +// +PRIVATE +void AcDisplayMessage() +{ + char *msgtext; + if ( AcFetchStringParam( &msgtext, ACM_EAT_SPACE( ACM_DISPLAYMESSAGE ) ) ) { + + ShowMessage( msgtext ); + } +} + + +// execute a command supplied as string --------------------------------------- +// +PRIVATE +void AcExecCommandString() +{ + // make sure this is called from within a compiled demo + if ( bin_params == NULL ) { + CON_AddLine( "only valid during binary replay." ); + return; + } + + //NOTE: + // extreme care must be taken which commands are supplied to this + // function. right now, there are no safety checks for commands + // that must not be executed using this function. + + char *command; + if ( AcFetchStringParam( &command, ACM_EAT_SPACE( ACM_EXECCOMMAND ) ) ) { + + // command must belong to the class of non-compilable commands + ProcessExternalLine( command ); + ExecNonCompilableCommand( command ); + } +} + + +// macro to return with error message if recording inactive ------------------- +// +#define CHECK_RECORDING_STATE() \ +\ +if ( !RecordingActive ) { \ + CON_AddLine( no_batch_open ); \ + return; \ +} + + +// save all objects from specified object list -------------------------------- +// +PRIVATE +void AcSaveObjectList() +{ + CHECK_RECORDING_STATE(); + + // disallow object camera + if ( ObjCameraActive ) { + CON_AddLine( no_objcam_allowed ); + return; + } + + int32 listid; + if ( AcFetchIntParams( 1, &listid ) ) { + + switch ( listid ) { + + case PSHIP_LIST_NO: + Save_ObjListShips( RecordingFp ); + break; + + case LASER_LIST_NO: + Save_ObjListLasers( RecordingFp ); + break; + + case MISSL_LIST_NO: + Save_ObjListMissls( RecordingFp ); + break; + + case EXTRA_LIST_NO: + Save_ObjListExtras( RecordingFp ); + break; + + case CUSTM_LIST_NO: + Save_ObjListCustom( RecordingFp ); + break; + + default: + CON_AddLine( invalid_list ); + } + } +} + + +// save pseudo star positions ------------------------------------------------- +// +PRIVATE +void AcSavePseudoStars() +{ + CHECK_RECORDING_STATE(); + Save_PseudoStars( RecordingFp ); +} + + +// save camera position and orientation --------------------------------------- +// +PRIVATE +void AcSaveCamera() +{ + CHECK_RECORDING_STATE(); + Save_Camera( RecordingFp ); +} + + +// save fixed stars orientation ----------------------------------------------- +// +PRIVATE +void AcSaveFixedStars() +{ + // dummy for compatibility +} + + +// save state of all remote players ------------------------------------------- +// +PRIVATE +void AcSaveRemoteState() +{ + CHECK_RECORDING_STATE(); + Save_RemoteState( RecordingFp ); +} + + +// kill all pseudo stars ------------------------------------------------------ +// +PRIVATE +void AcKillPseudoStars() +{ + NumPseudoStars = 0; +} + + +// add single pseudo star ----------------------------------------------------- +// +PRIVATE +void AcAddPseudoStar() +{ + if ( NumPseudoStars < MAX_PSEUDO_STARS ) { + hprec_t pos[ 3 ]; + if ( AcFetchFloatParams( 3, pos ) ) { + int no = NumPseudoStars++; + PseudoStars[ no ].X = FLOAT_TO_GEOMV( pos[ 0 ] ); + PseudoStars[ no ].Y = FLOAT_TO_GEOMV( pos[ 1 ] ); + PseudoStars[ no ].Z = FLOAT_TO_GEOMV( pos[ 2 ] ); + } + } else { + CON_AddLine( too_many_pseudos ); + } +} + + +// prepare restoration of data screen shot ------------------------------------ +// +PRIVATE +void AcPrepareDataRestore() +{ + int shipclass = MyShip->ObjectClass; + + // allow optional specification of ship class + int32 sclass; + if ( AcFetchIntParams( 1, &sclass ) ) { + shipclass = sclass; + } + + // free objects and particles + KillAllObjects(); + + // delete pseudo stars + AcKillPseudoStars(); + +#ifdef REINIT_LOCAL_SHIP_ON_PREP_RESTORE + + // reinit local player's ship + InitLocalShipStatus( shipclass ); + InitHudDisplay(); + +#endif // REINIT_LOCAL_SHIP_ON_PREP_RESTORE + + // globally select shipclass + LocalShipClass = MyShip->ObjectClass; + + // set flag that view camera filter has to be reset + // after the new matrix has been set + reset_viewcam_filter_on_update = TRUE; + + // reset mapping table for class ids + ResetClassMapTable(); +} + + +// save data screen shot ------------------------------------------------------ +// +PRIVATE +void AcSaveDataInfo() +{ + //NOTE: + // this function tries to create the logical analog to a screenshot. + // for this, it records the current state (that is, commands that + // are able to restore the current state on their execution). + + CHECK_RECORDING_STATE(); + Save_StateInfo( RecordingFp ); +} + + +// fade screen out (to black) ------------------------------------------------- +// +PRIVATE +void AcFadeOut() +{ +// VIDs_FadeScreenToBlack( PAL_GAME, FALSE ); + + int32 speed; + if ( AcFetchIntParams( 1, &speed ) ) { + + SetScreenFadeSpeed = speed; + + SetScreenFadeColor.R = 0; + SetScreenFadeColor.G = 0; + SetScreenFadeColor.B = 0; +// SetScreenFadeColor.A = irrelevant; + + // continue fading from current value + if ( SetScreenFade == 0 ) { + SetScreenFade = 0xff00; + } else if ( SetScreenFade < 0 ) { + SetScreenFade += 0xff00; + if ( SetScreenFade < 0 ) { + SetScreenFade = 0; + } + } + } +} + + +// fade screen in (from black) ------------------------------------------------ +// +PRIVATE +void AcFadeIn() +{ +// VIDs_FadeScreenFromBlack( PAL_GAME ); + + int32 speed; + if ( AcFetchIntParams( 1, &speed ) ) { + + SetScreenFadeSpeed = speed; + + SetScreenFadeColor.R = 0; + SetScreenFadeColor.G = 0; + SetScreenFadeColor.B = 0; +// SetScreenFadeColor.A = irrelevant; + + // continue fading from current value + if ( ( SetScreenFade == 0 ) || ( SetScreenFade == 1 ) ) { + SetScreenFade = -0xff00; + } else if ( SetScreenFade > 0 ) { + SetScreenFade += -0xff00; + if ( SetScreenFade > 0 ) { + SetScreenFade = 0; + } + } + } +} + + +// fade screen out (to white) ------------------------------------------------- +// +PRIVATE +void AcWhiteFadeOut() +{ +// colrgba_s scol = COLRGBA_WHITE; +// VIDs_SetScreenToColor( scol ); + + int32 speed; + if ( AcFetchIntParams( 1, &speed ) ) { + + SetScreenFadeSpeed = speed; + + SetScreenFadeColor.R = 255; + SetScreenFadeColor.G = 255; + SetScreenFadeColor.B = 255; +// SetScreenFadeColor.A = irrelevant; + + // continue fading from current value + if ( SetScreenFade == 0 ) { + SetScreenFade = 0xff00; + } else if ( SetScreenFade < 0 ) { + SetScreenFade += 0xff00; + if ( SetScreenFade < 0 ) { + SetScreenFade = 0; + } + } + } +} + + +// fade screen in (from white) ------------------------------------------------ +// +PRIVATE +void AcWhiteFadeIn() +{ +// VIDs_FadeScreenFromWhite( PAL_GAME ); + + int32 speed; + if ( AcFetchIntParams( 1, &speed ) ) { + + SetScreenFadeSpeed = speed; + + SetScreenFadeColor.R = 255; + SetScreenFadeColor.G = 255; + SetScreenFadeColor.B = 255; +// SetScreenFadeColor.A = irrelevant; + + // continue fading from current value + if ( ( SetScreenFade == 0 ) || ( SetScreenFade == 1 ) ) { + SetScreenFade = -0xff00; + } else if ( SetScreenFade > 0 ) { + SetScreenFade += -0xff00; + if ( SetScreenFade > 0 ) { + SetScreenFade = 0; + } + } + } +} + + +// set standard palette ------------------------------------------------------- +// +PRIVATE +void AcStandardPalette() +{ +// AwaitVertSync(); + + // turn off fading + SetScreenFade = 0; +} + + +// set entire palette to black ------------------------------------------------ +// +PRIVATE +void AcBlackScreen() +{ +// colrgba_s scol = COLRGBA_BLACK; +// VIDs_SetScreenToColor( scol ); + + SetScreenFadeColor.R = 0; + SetScreenFadeColor.G = 0; + SetScreenFadeColor.B = 0; +// SetScreenFadeColor.A = irrelevant; + + // hold fading at opaque level + SetScreenFade = 1; +} + + +// set entire palette to white ------------------------------------------------ +// +PRIVATE +void AcWhiteScreen() +{ +// colrgba_s scol = COLRGBA_WHITE; +// VIDs_SetScreenToColor( scol ); + + SetScreenFadeColor.R = 255; + SetScreenFadeColor.G = 255; + SetScreenFadeColor.B = 255; +// SetScreenFadeColor.A = irrelevant; + + // hold fading at opaque level + SetScreenFade = 1; +} + + +// set speed property of laser object ----------------------------------------- +// +PRIVATE +void AcSetLaserSpeed() +{ + fixed_t speed; + if ( AcFetchIntParams( 1, (int32 *) &speed ) ) { + LaserObject *scanpo = FetchFirstLaser(); + ASSERT( scanpo != NULL ); + scanpo->Speed = speed; + } +} + + +// set direction vector property of laser object ------------------------------ +// +PRIVATE +void AcSetLaserDirVec() +{ + hprec_t vec[ 3 ]; + if ( AcFetchFloatParams( 3, vec ) ) { + LaserObject *scanpo = FetchFirstLaser(); + ASSERT( scanpo != NULL ); + scanpo->DirectionVec.X = FLOAT_TO_GEOMV( vec[ 0 ] ); + scanpo->DirectionVec.Y = FLOAT_TO_GEOMV( vec[ 1 ] ); + scanpo->DirectionVec.Z = FLOAT_TO_GEOMV( vec[ 2 ] ); + } +} + + +// set owner property of laser object ----------------------------------------- +// +PRIVATE +void AcSetLaserOwner() +{ + int32 owner; + if ( AcFetchIntParams( 1, &owner ) ) { + LaserObject *scanpo = FetchFirstLaser(); + ASSERT( scanpo != NULL ); + scanpo->Owner = owner; + } +} + + +// set speed property of missile object --------------------------------------- +// +PRIVATE +void AcSetMisslSpeed() +{ + fixed_t speed; + if ( AcFetchIntParams( 1, (int32 *) &speed ) ) { + MissileObject *scanpo = FetchFirstMissile(); + ASSERT( scanpo != NULL ); + scanpo->Speed = speed; + } + +} + + +// set direction vector property of missile object ---------------------------- +// +PRIVATE +void AcSetMisslDirVec() +{ + hprec_t vec[ 3 ]; + if ( AcFetchFloatParams( 3, vec ) ) { + MissileObject *scanpo = FetchFirstMissile(); + ASSERT( scanpo != NULL ); + scanpo->DirectionVec.X = FLOAT_TO_GEOMV( vec[ 0 ] ); + scanpo->DirectionVec.Y = FLOAT_TO_GEOMV( vec[ 1 ] ); + scanpo->DirectionVec.Z = FLOAT_TO_GEOMV( vec[ 2 ] ); + } +} + + +// set owner property of missile object --------------------------------------- +// +PRIVATE +void AcSetMisslOwner() +{ + int32 owner; + if ( AcFetchIntParams( 1, &owner ) ) { + MissileObject *scanpo = FetchFirstMissile(); + ASSERT( scanpo != NULL ); + scanpo->Owner = owner; + } +} + + +// set target id property of missile object ----------------------------------- +// +PRIVATE +void AcSetMisslTarget() +{ + //NOTE: + // this command will only occur to set the target + // of a guided missile fired by the local player. + + int32 target; + if ( AcFetchIntParams( 1, &target ) ) { + + TargetMissileObject *scanpo = (TargetMissileObject *) FetchFirstMissile(); + ASSERT( scanpo != NULL ); + ASSERT( ( scanpo->ObjectType & TYPECONTROLMASK ) == TYPEMISSILEISHOMING ); + scanpo->TargetObjNumber = target; + +#ifdef RECOVER_TARGET_ON_MISSILE_CREATION + + if ( TargetObjNumber != (dword)target ) { + + // set selected target to ensure the current + // selection is not wrong due to a lost keypress + TargetObjNumber = target; + CON_AddLine( "recovering target." ); + } +#endif + + } +} + + +// set owner property of mine object ------------------------------------------ +// +PRIVATE +void AcSetMineOwner() +{ + int32 owner; + if ( AcFetchIntParams( 1, &owner ) ) { + MineObject *scanpo = (MineObject *) FetchFirstExtra(); + ASSERT( scanpo != NULL ); + scanpo->Owner = owner; + } +} + + +// create an extra ------------------------------------------------------------ +// +PRIVATE +void AcCreateExtra() +{ + ASSERT( !delayed_object_creation ); + + int32 objclass; + if ( AcFetchIntParams( 1, &objclass ) ) { + + if ( (dword)objclass >= MAX_DISTINCT_OBJCLASSES ) { + CON_AddLine( invalid_id_range ); + return; + } + + // map the recorded class id to the corresponding current class id + if ( class_map_id_to_name[ objclass ] != CLASS_ID_INVALID ) { + objclass = class_map_id_to_name[ objclass ]; + } + + // create extra corresponding to original class + Xmatrx im; + MakeIdMatrx( im ); + ExtraObject *extrapo = (ExtraObject *) CreateObject( objclass, im ); + if ( extrapo == NULL ) { + CON_AddLine( invalid_class ); + } else { + OBJ_FillExtraMemberVars( extrapo ); + } + } +} + + +// create an energy field ----------------------------------------------------- +// +PRIVATE +void AcEnergyField() +{ + hprec_t vec[ 3 ]; + if ( AcFetchFloatParams( 3, vec ) ) { + Vertex3 origin; + origin.X = FLOAT_TO_GEOMV( vec[ 0 ] ); + origin.Y = FLOAT_TO_GEOMV( vec[ 1 ] ); + origin.Z = FLOAT_TO_GEOMV( vec[ 2 ] ); + SFX_CreateEnergyField( origin ); + } +} + + +// shoot spreadfire gun ------------------------------------------------------- +// +PRIVATE +void AcSpreadfire() +{ + WFX_ShootParticleWeapon( MyShip, PARTICLEGUN_SPREADFIRE ); +} + + +// activate lightning --------------------------------------------------------- +// +PRIVATE +void AcLightningOn() +{ + if ( ( MyShip->WeaponsActive & WPMASK_CANNON_LIGHTNING ) == 0 ) { + WFX_ActivateLightning( MyShip ); + } else { + CON_AddLine( "filtering redundant lightning activation." ); + } +} + + +// deactivate lightning ------------------------------------------------------- +// +PRIVATE +void AcLightningOff() +{ + if ( ( MyShip->WeaponsActive & WPMASK_CANNON_LIGHTNING ) != 0 ) { + WFX_DeactivateLightning( MyShip ); + } else { + CON_AddLine( "filtering redundant lightning deactivation." ); + } +} + + +// activate helix ------------------------------------------------------------- +// +void AcHelixOn() +{ + if ( ( MyShip->WeaponsActive & WPMASK_CANNON_HELIX ) == 0 ) { + WFX_ActivateHelix( MyShip ); + } else { + CON_AddLine( "filtering redundant helix activation." ); + } +} + + +// deactivate helix ----------------------------------------------------------- +// +void AcHelixOff() +{ + if ( ( MyShip->WeaponsActive & WPMASK_CANNON_HELIX ) != 0 ) { + WFX_DeactivateHelix( MyShip ); + } else { + CON_AddLine( "filtering redundant helix deactivation." ); + } +} + + +// activate photon ------------------------------------------------------------ +// +void AcPhotonOn() +{ + if ( ( MyShip->WeaponsActive & WPMASK_CANNON_PHOTON ) == 0 ) { + WFX_ActivatePhoton( MyShip ); + } else { + CON_AddLine( "filtering redundant photon activation." ); + } +} + + +// deactivate photon ---------------------------------------------------------- +// +void AcPhotonOff() +{ + if ( ( MyShip->WeaponsActive & WPMASK_CANNON_PHOTON ) != 0 ) { + WFX_DeactivatePhoton( MyShip ); + } else { + CON_AddLine( "filtering redundant photon deactivation." ); + } +} + + +// activate emp --------------------------------------------------------------- +// +void AcEmpOn() +{ + if ( ( MyShip->WeaponsActive & WPMASK_DEVICE_EMP ) == 0 ) { + WFX_ActivateEmp( MyShip ); + } else { + CON_AddLine( "filtering redundant emp activation." ); + } +} + + +// deactivate emp ------------------------------------------------------------- +// +void AcEmpOff() +{ + if ( ( MyShip->WeaponsActive & WPMASK_DEVICE_EMP) != 0 ) { + WFX_DeactivateEmp( MyShip ); + } else { + CON_AddLine( "filtering redundant emp deactivation." ); + } +} + + +// fire emp ------------------------------------------------------------------- +// +void AcEmp() +{ + WFX_EmpBlast( MyShip ); +} + + +// set id of ship object that is first in list to specific value -------------- +// +PRIVATE +void AcSetObjectId() +{ + int32 objid; + if ( AcFetchIntParams( 1, &objid ) ) { + if ( delayed_object_creation ) { + delayed_object_id = objid; + } else { + ShipObject *scanpo = FetchFirstShip(); + // ship must have been created previously + ASSERT( scanpo != NULL ); + if ( scanpo != NULL ) { + scanpo->ObjectNumber = objid; + } + } + } +} + + +// set host id of object to specific value to enable targeting for missiles --- +// +PRIVATE +void AcSetObjectHostId() +{ + int32 objid; + if ( AcFetchIntParams( 1, &objid ) ) { + if ( delayed_object_creation ) { + delayed_object_hostid = objid; + } else { + ShipObject *scanpo = FetchFirstShip(); + // ship must have been created previously + ASSERT( scanpo != NULL ); + if ( scanpo != NULL ) { + scanpo->HostObjNumber = objid; + } + } + } +} + + +// simulate depression of single key ------------------------------------------ +// +PRIVATE +void AcSimulateKeyPress() +{ + int32 keynum; + if ( AcFetchIntParams( 1, &keynum ) ) { + if ( (dword)keynum < NUM_GAMEFUNC_KEYS ) { + + ASSERT( sizeof( DepressedKeys->key_Escape ) == sizeof( dword ) ); + ((dword*)DepressedKeys)[ keynum ] = 1; + ((dword*)key_replay_map)[ keynum ] = 1; + + // explicitly check for object camera toggling + if ( offsetof( keyfunc_s, key_ToggleObjCamera ) / sizeof( DepressedKeys->key_Escape ) == keynum ) { + ReplayObjCamActive = !ReplayObjCamActive; + } + + } else { + CON_AddLine( invalid_key_id ); + } + } +} + + +// simulate release of single key --------------------------------------------- +// +PRIVATE +void AcSimulateKeyRelease() +{ + int32 keynum; + if ( AcFetchIntParams( 1, &keynum ) ) { + if ( (dword)keynum < NUM_GAMEFUNC_KEYS ) { + ASSERT( sizeof( DepressedKeys->key_Escape ) == sizeof( dword ) ); + ((dword*)DepressedKeys)[ keynum ] = 0; + ((dword*)key_replay_map)[ keynum ] = 0; + } else { + CON_AddLine( invalid_key_id ); + } + } +} + + +// ---------------------------------------------------------------------------- +// local ship configuration commands - +// ---------------------------------------------------------------------------- + + +// current damage ------------------------------------------------------------- +// +PRIVATE +void AcMyShip_CurDamage() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->CurDamage = ivalue; + } +} + + +// maximum damage ------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxDamage() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->MaxDamage = ivalue; + } +} + + +// current energy ------------------------------------------------------------- +// +PRIVATE +void AcMyShip_CurEnergy() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->CurEnergy = ivalue; + } +} + + +// maximum energy ------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxEnergy() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->MaxEnergy = ivalue; + } +} + + +// current speed -------------------------------------------------------------- +// +PRIVATE +void AcMyShip_CurSpeed() +{ + fixed_t ivalue; + if ( AcFetchIntParams( 1, (int32 *) &ivalue ) ) { + MyShip->CurSpeed = ivalue; + } +} + + +// maximum speed -------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxSpeed() +{ + fixed_t ivalue; + if ( AcFetchIntParams( 1, (int32 *) &ivalue ) ) { + MyShip->MaxSpeed = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_NumMissls() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->NumMissls = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxNumMissls() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->MaxNumMissls = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_NumHomMissls() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->NumHomMissls = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxNumHomMissls() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->MaxNumHomMissls = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_NumPartMissls() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->NumPartMissls = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxNumPartMissls() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->MaxNumPartMissls = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_NumMines() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->NumMines = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_MaxNumMines() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->MaxNumMines = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_Weapons() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->Weapons = ivalue; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_WeaponsActive() +{ + //NOTE: + // if new duration weapons are added this function + // should be updated. + + int32 weaponsactive; + if ( AcFetchIntParams( 1, &weaponsactive ) ) { + + // check for lightning state change + dword oldstate = MyShip->WeaponsActive & WPMASK_CANNON_LIGHTNING; + dword newstate = weaponsactive & WPMASK_CANNON_LIGHTNING; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_ActivateLightning( MyShip ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_DeactivateLightning( MyShip ); + } + + // check for helix state change + oldstate = MyShip->WeaponsActive & WPMASK_CANNON_HELIX; + newstate = weaponsactive & WPMASK_CANNON_HELIX; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_ActivateHelix( MyShip ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_DeactivateHelix( MyShip ); + } + + // check for photon state change + oldstate = MyShip->WeaponsActive & WPMASK_CANNON_PHOTON; + newstate = weaponsactive & WPMASK_CANNON_PHOTON; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_ActivatePhoton( MyShip ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_DeactivatePhoton( MyShip ); + } + + // check for emp state change + oldstate = MyShip->WeaponsActive & WPMASK_DEVICE_EMP; + newstate = weaponsactive & WPMASK_DEVICE_EMP; + if ( ( oldstate == 0 ) && ( newstate != 0 ) ) { + WFX_ActivateEmp( MyShip ); + } else if ( ( oldstate != 0 ) && ( newstate == 0 ) ) { + WFX_DeactivateEmp( MyShip ); + } + + // fallback for unknown duration weapons + // (simply set/reset activation bits) + dword unknownmask = 0xffffffff; + unknownmask &= ~WPMASK_CANNON_LIGHTNING; + unknownmask &= ~WPMASK_CANNON_HELIX; + unknownmask &= ~WPMASK_CANNON_PHOTON; + unknownmask &= ~WPMASK_DEVICE_EMP; + MyShip->WeaponsActive &= ~unknownmask; + MyShip->WeaponsActive |= weaponsactive & unknownmask; + } +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void AcMyShip_Specials() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + MyShip->Specials = ivalue; + } +} + + +// global variables configuration commands pertaining to local ship ----------- +// +PRIVATE +void AcGlobals_SelectedLaser() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + SelectedLaser = ivalue; + } +} + +PRIVATE +void AcGlobals_SelectedMissile() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + SelectedMissile = ivalue; + } +} + +PRIVATE +void AcGlobals_CurGun() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + CurGun = ivalue; + } +} + +PRIVATE +void AcGlobals_CurLauncher() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + CurLauncher = ivalue; + } +} + +PRIVATE +void AcGlobals_AUX_HUD_PANEL_3_CONTROL() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + AUX_HUD_PANEL_3_CONTROL = ivalue; + } +} + +PRIVATE +void AcGlobals_AUX_HUD_PANEL_4_CONTROL() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + AUX_HUD_PANEL_4_CONTROL = ivalue; + } +} + +PRIVATE +void AcGlobals_TargetObjNumber() +{ + int32 ivalue; + if ( AcFetchIntParams( 1, &ivalue ) ) { + TargetObjNumber = ivalue; + } +} + + +// play specified sound effect ------------------------------------------------ +// +PRIVATE +void AcPlaySound() +{ + // dummy for compatibility +} + + +// flag whether audio stream has been started with an action command ---------- +// +PUBLIC int con_audio_stream_started = FALSE; + + +// start playing of specific audio stream ------------------------------------- +// +PRIVATE +void AcPlayStream() +{ + char *streamname; + if ( AcFetchStringParam( &streamname, ACM_EAT_SPACE( ACM_PLAYSTREAM ) ) ) { + + if ( strlen( streamname ) + strlen( console_audio_stream_path ) > PATH_MAX ) { + // resulting file name too long + CON_AddLine( stream_name_inval ); + return; + } + + //NOTE: + // apart from its length the filename is + // not checked for validity in any way! + + // create full filename including path + char fname[ PATH_MAX + 1 ]; + strcpy( fname, console_audio_stream_path ); + strcat( fname, streamname ); + + // check first if file exists in pack or current directory + FILE *fp = SYS_fopen( streamname, "rb" ); + if ( fp == NULL ) { + + // check if file exists in audio stream path + fp = SYS_fopen( fname, "rb" ); + if ( fp == NULL ) { + CON_AddLine( stream_name_inval ); + return; + } + + //NOTE: + // we use SYS_fopen() here, because the streaming code + // also uses the SYS_f*() functions. + + } else { + + // strip path + strcpy( fname, streamname ); + } + SYS_fclose( fp ); + + // play audio stream (automatically determines stream's format) + int started = AUDs_PlayAudioStream( fname ); + + if ( started ) { + con_audio_stream_started = TRUE; + } else { + CON_AddLine( no_stream_started ); + } + } +} + + +// stop playing of currently active audio stream ------------------------------ +// +PRIVATE +void AcStopStream() +{ + int stopped = AUDs_StopAudioStream(); + + if ( stopped ) { + con_audio_stream_started = FALSE; + } else { + CON_AddLine( no_stream_stopped ); + } +} + + +// set aux flag with ac. command ---------------------------------------------- +// +PRIVATE +void AcSetAuxFlag() +{ + int32 params[ 2 ]; + if ( AcFetchIntParams( 2, params ) ) { + + if ( (dword)params[ 0 ] < MAX_AUX_ENABLING ) { + AuxEnabling[ params[ 0 ] ] = params[ 1 ]; + } + } +} + + +// set aux data with ac. command ---------------------------------------------- +// +PRIVATE +void AcSetAuxData() +{ + int32 params[ 2 ]; + if ( AcFetchIntParams( 2, params ) ) { + + if ( (dword)params[ 0 ] < MAX_AUX_DATA ) { + AuxData[ params[ 0 ] ] = params[ 1 ]; + } + } +} + + +// set new refframe frequency ------------------------------------------------- +// +PRIVATE +void AcSetRefFrameFrequency() +{ + int32 param; + if ( AcFetchIntParams( 1, ¶m ) ) { + + if ( RefFrameFrequency != param ) { + + RefFrameFrequency = param; + + // reinit frame timer to apply frequency change + SYSs_InitFrameTimer(); + } + } +} + + +// alter entry-mode flag ------------------------------------------------------ +// +PRIVATE +void AcSetEntryMode() +{ + int32 param; + if ( AcFetchIntParams( 1, ¶m ) ) { + + EntryMode = param; + InFloatingMenu = EntryMode ? FloatingMenu : FALSE; + + // reset the floating menu state + if ( InFloatingMenu ) { + ActivateFloatingMenu( FALSE ); + } + } +} + + +// this gets called on execution instead of compilation, which is a nop ------- +// +PRIVATE +void AcIncludeDemo() +{ + //NOTE: + // this command is a nop in a script file and should never + // occur in a compiled demo, since it will be substituted + // by the specified demo on compilation. + + CON_AddLine( only_for_compile ); +} + + +// this gets called on execution instead of compilation, which is a nop ------- +// +PRIVATE +void AcScheduleCommand() +{ + //NOTE: + // this command is a nop in a script file. + // in a compiled demo this function will not be called at all. + + CON_AddLine( only_for_compile ); +} + + +// set the ambient light color ------------------------------------------------ +// +PRIVATE +void AcLightAmbient() +{ + int32 params[ 4 ]; + if ( AcFetchIntParams( 4, params ) ) { + for (int i = 0; i < 4; i++) + LightColorAmbient.index[i] = params[i]; + } +} + + +// set the diffuse light color ------------------------------------------------ +// +PRIVATE +void AcLightDiffuse() +{ + int32 params[ 4 ]; + if ( AcFetchIntParams( 4, params ) ) { + for (int i = 0; i < 4; i++) + LightColorDiffuse.index[i] = params[i]; + } +} + + +// set the specular light color ----------------------------------------------- +// +PRIVATE +void AcLightSpecular() +{ + int32 params[ 4 ]; + if ( AcFetchIntParams( 4, params ) ) { + for (int i = 0; i < 4; i++) + LightColorSpecular.index[i] = params[i]; + } +} + + +// cd audio: open drive ------------------------------------------------------- +// +PRIVATE +void AcCD_Open() +{ + int32 param; + if ( AcFetchIntParams( 1, ¶m ) ) { + + //AUDs_CDOpen( param ); + } +} + + +// cd audio: close drive ------------------------------------------------------ +// +PRIVATE +void AcCD_Close() +{ + //AUDs_CDClose(); +} + + +// cd audio: play audio track ------------------------------------------------- +// +PRIVATE +void AcCD_Play() +{ + //NOTE: + // the from and to params (param 1 and 2) cannot be omitted + // when using this command. however, they can be set to -1 + // in order to avoid specifying specific from/to locations. + + int32 params[ 3 ]; + if ( AcFetchIntParams( 3, params ) ) { + + //AUDs_CDPlay( params[ 0 ], params[ 1 ], params[ 2 ] ); + } +} + + +// cd audio: pause playing ---------------------------------------------------- +// +PRIVATE +void AcCD_Pause() +{ + //AUDs_CDPause(); +} + + +// cd audio: resume playing --------------------------------------------------- +// +PRIVATE +void AcCD_Resume() +{ + //AUDs_CDResume(); +} + + +// cd audio: stop playing ----------------------------------------------------- +// +PRIVATE +void AcCD_Stop() +{ + //AUDs_CDStop(); +} + + +// cd audio: set volume ------------------------------------------------------- +// +PRIVATE +void AcCD_Volume() +{ + int32 param; + if ( AcFetchIntParams( 1, ¶m ) ) { + + //AUDs_CDSetVolume( param ); + } +} + + +// list of valid action commands and functions to be called for each ---------- +// +act_command_s action_commands[] = { + + // general signature + { "ac.", NULL, ACF_NODIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + + { "ac.wait", AcIdleCommand, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.pitch", AcAutoPitch, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.yaw", AcAutoYaw, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.roll", AcAutoRoll, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.slidex", AcAutoSlideX, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 1 }, + { "ac.slidey", AcAutoSlideY, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 1 }, + { "ac.move", AcAutoMove, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.camrot1", AcSetCamRotCol1, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.camrot2", AcSetCamRotCol2, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.camrot3", AcSetCamRotCol3, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.camorigin", AcSetCamOrigin, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + + { "ac.fixrot1", AcSetFixedStarRotCol1, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.fixrot2", AcSetFixedStarRotCol2, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.fixrot3", AcSetFixedStarRotCol3, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + + { "ac.packet", AcPlayRemotePacket, ACF_NODIRECT | ACF_COMPILE | ACF_PACKETPARAM, 1 }, + + { "ac.fadeout", AcFadeOut, ACF_DIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.fadein", AcFadeIn, ACF_DIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.wfadeout", AcWhiteFadeOut, ACF_DIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.wfadein", AcWhiteFadeIn, ACF_DIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.black", AcBlackScreen, ACF_DIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.white", AcWhiteScreen, ACF_DIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.stdpalette", AcStandardPalette, ACF_DIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + + { "ac.savescreen", AcSaveDataInfo, ACF_DIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + { "ac.savelist", AcSaveObjectList, ACF_DIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + { "ac.savecam", AcSaveCamera, ACF_DIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + { "ac.savefstars", AcSaveFixedStars, ACF_DIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + { "ac.savepstars", AcSavePseudoStars, ACF_DIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + { "ac.saveremote", AcSaveRemoteState, ACF_DIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + + { "ac.killpstars", AcKillPseudoStars, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.addpstar", AcAddPseudoStar, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + + { "ac.preprestore", AcPrepareDataRestore, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.creatobj", AcCreateObject, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.creatextra", AcCreateExtra, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.destlist", AcDestroyObjectList, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.remoteplayer", AcRemotePlayer, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 4 }, + { "ac.remotematrix", AcRemoteMatrix, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 12 }, + { "ac.remotename", AcRemoteName, ACF_NODIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + { "ac.remotejoin", AcRemoteJoin, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 3 }, + { "ac.remoteunjoin", AcRemoteUnjoin, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 3 }, + + { "ac.cleardemo", AcClearDemo, ACF_DIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.objmatrxcol1", AcObjectMatrxColumn1, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 4 }, + { "ac.objmatrxcol2", AcObjectMatrxColumn2, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 4 }, + { "ac.objmatrxcol3", AcObjectMatrxColumn3, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 4 }, + { "ac.objmatrxcol4", AcObjectMatrxColumn4, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 4 }, + + { "ac.laserspeed", AcSetLaserSpeed, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.laserdirvec", AcSetLaserDirVec, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.laserowner", AcSetLaserOwner, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.misslspeed", AcSetMisslSpeed, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.missldirvec", AcSetMisslDirVec, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + + { "ac.misslowner", AcSetMisslOwner, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.missltarget", AcSetMisslTarget, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.mineowner", AcSetMineOwner, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.energyfield", AcEnergyField, ACF_NODIRECT | ACF_COMPILE | ACF_FLOATPARAMS, 3 }, + { "ac.spreadfire", AcSpreadfire, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.lightningon", AcLightningOn, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.lightningoff", AcLightningOff, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + + { "ac.setobjid", AcSetObjectId, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.setobjhostid", AcSetObjectHostId, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.keypress", AcSimulateKeyPress, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.keyrelease", AcSimulateKeyRelease, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.ms.curdamage", AcMyShip_CurDamage, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxdamage", AcMyShip_MaxDamage, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.curenergy", AcMyShip_CurEnergy, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxenergy", AcMyShip_MaxEnergy, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.curspeed", AcMyShip_CurSpeed, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxspeed", AcMyShip_MaxSpeed, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.nummissls", AcMyShip_NumMissls, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxnummissls", AcMyShip_MaxNumMissls, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.numhommissls", AcMyShip_NumHomMissls, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxnumhommissls", AcMyShip_MaxNumHomMissls, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.nummines", AcMyShip_NumMines, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxnummines", AcMyShip_MaxNumMines, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.weapons", AcMyShip_Weapons, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.specials", AcMyShip_Specials, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.gl.selectedlaser", AcGlobals_SelectedLaser, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.gl.selectedmissile", AcGlobals_SelectedMissile, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.gl.curgun", AcGlobals_CurGun, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.gl.curlauncher", AcGlobals_CurLauncher, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.gl.panel3control", AcGlobals_AUX_HUD_PANEL_3_CONTROL, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.gl.panel4control", AcGlobals_AUX_HUD_PANEL_4_CONTROL, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.gl.targetobjnumber", AcGlobals_TargetObjNumber, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.writesmall", AcWriteSmall, ACF_DIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + { "ac.writebig", AcWriteBig, ACF_DIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + { "ac.writebig2", AcWriteBig2, ACF_DIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + { "ac.writebig3", AcWriteBig3, ACF_DIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + { "ac.cleartext", AcClearText, ACF_DIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + + { "ac.playstream", AcPlayStream, ACF_DIRECT | ACF_COMPILE | ACF_STRINGSTRIP, 1 }, + { "ac.stopstream", AcStopStream, ACF_DIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.playsound", AcPlaySound, ACF_DIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.aux", AcSetAuxFlag, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 2 }, + { "ac.entrymode", AcSetEntryMode, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.servermsg", AcPlayServerMessage, ACF_NODIRECT | ACF_COMPILE | ACF_STRINGSTRIP, 1 }, + + { "ac.helixon", AcHelixOn, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.helixoff", AcHelixOff, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + + { "ac.remotemaxplayers", AcRemoteMaxPlayers, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.include", AcIncludeDemo, ACF_NODIRECT | ACF_COMPILE | ACF_DEMOPARAM, 1 }, + + { "ac.ms.weaponsactive", AcMyShip_WeaponsActive, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.remoteweaponsactive", AcRemoteWeaponsActive, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.write", AcWriteConsoleText, ACF_NODIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + { "ac.display", AcDisplayMessage, ACF_NODIRECT | ACF_COMPILE | ACF_STRINGSTRIP, 1 }, + + { "ac.cd.open", AcCD_Open, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.cd.close", AcCD_Close, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.cd.play", AcCD_Play, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 3 }, + { "ac.cd.pause", AcCD_Pause, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.cd.resume", AcCD_Resume, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.cd.stop", AcCD_Stop, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.cd.volume", AcCD_Volume, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.command", AcExecCommandString, ACF_NODIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + + { "ac.classmapid", AcClassMapId, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.classmapname", AcClassMapName, ACF_NODIRECT | ACF_COMPILE | ACF_STRINGPARAM, 1 }, + + { "ac.auxdata", AcSetAuxData, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 2 }, + { "ac.refframes", AcSetRefFrameFrequency, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.schedule", AcScheduleCommand, ACF_NODIRECT | ACF_COMPILE | ACF_SCHEDPARAM, 1 }, + + { "ac.ambient", AcLightAmbient, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 4 }, + { "ac.diffuse", AcLightDiffuse, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 4 }, + { "ac.specular", AcLightSpecular, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 4 }, + + { "ac.ms.numpartmissls", AcMyShip_NumPartMissls, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + { "ac.ms.maxnumpartmissls", AcMyShip_MaxNumPartMissls, ACF_NODIRECT | ACF_COMPILE | ACF_INTPARAMS, 1 }, + + { "ac.photonon", AcPhotonOn, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.photonoff", AcPhotonOff, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + + { "ac.empon", AcEmpOn, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.empoff", AcEmpOff, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + { "ac.emp", AcEmp, ACF_NODIRECT | ACF_COMPILE | ACF_NOPARAMS, 0 }, + + { NULL, NULL, ACF_NODIRECT | ACF_NOCOMPILE | ACF_NOPARAMS, 0 }, + +}; + + +// determine the number of parameter bytes of an action command --------------- +// +size_t GetActionParamSize( int actid, char *params ) +{ + ASSERT( actid > ACM_SIGNATURE ); + ASSERT( params != NULL ); + + size_t paramsize = 0; + + if ( action_commands[ actid ].flags & ACF_INTPARAMS ) { + paramsize = sizeof( int32 ) * action_commands[ actid ].numparameters; + } else if ( action_commands[ actid ].flags & ACF_FLOATPARAMS ) { + paramsize = sizeof( hprec_t ) * action_commands[ actid ].numparameters; + } else if ( action_commands[ actid ].flags & ACF_STRINGPARAM ) { + paramsize = strlen( params ) + 1; + } + + return paramsize; +} + + +// scheduled action commands -------------------------------------------------- +// +struct scheduled_command_s { + + refframe_t timestamp; + char* command; +}; + +#define MAX_SCHEDULED_COMMANDS 64 +static int num_scheduled_commands = 0; +static scheduled_command_s scheduled_commands[ MAX_SCHEDULED_COMMANDS ]; + + +// remainder of a wait interval split by a scheduled command ------------------ +// +static int scheduled_wait = 0; + + +// clear all scheduled action commands ---------------------------------------- +// +void ResetScheduledActions() +{ + num_scheduled_commands = 0; + scheduled_wait = 0; +} + + +// schedule an action command for automatic execution at a later time --------- +// +PRIVATE +size_t ScheduleCommand( int *params ) +{ + ASSERT( params != NULL ); + + // fetch delta time and command to schedule + int timedelta = SWAP_32( params[ 0 ] ); + int actid = SWAP_32( params[ 1 ] ); + + // calc absolute activation timestamp + refframe_t timestamp = demoinfo_curtime + timedelta; + int cid=0; + // insert at correct position if already commands scheduled + for ( cid = 0; cid < num_scheduled_commands; cid++ ) { + + if ( scheduled_commands[ cid ].timestamp >= timestamp ) { + + // this also ensures the move works correctly + if ( num_scheduled_commands < MAX_SCHEDULED_COMMANDS ) { + num_scheduled_commands++; + } + + // move back commands scheduled for a later time + if ( cid < MAX_SCHEDULED_COMMANDS - 1 ) { + size_t movesize = ( num_scheduled_commands - cid - 1 ); + movesize *= sizeof( scheduled_command_s ); + memmove( &scheduled_commands[ cid + 1 ], &scheduled_commands[ cid ], movesize ); + } + + // store this command + scheduled_commands[ cid ].timestamp = timestamp; + scheduled_commands[ cid ].command = (char *) ¶ms[ 1 ]; + break; + } + } + + // insert if no commands scheduled or position should be last + if ( cid == num_scheduled_commands ) { + + // commands that exceed the available space will be dropped silently + if ( cid < MAX_SCHEDULED_COMMANDS ) { + scheduled_commands[ cid ].timestamp = timestamp; + scheduled_commands[ cid ].command = (char *) ¶ms[ 1 ]; + num_scheduled_commands++; + } + } + + // return number of parameter bytes to skip + size_t paramsize = sizeof( int ) * 2; + paramsize += GetActionParamSize( actid, (char *) ¶ms[ 2 ] ); + return paramsize; +} + + +// execute command in binary format as written by WriteActionCommand() -------- +// +int ExecBinCommands( char* &data, int interactive ) +{ + // non-interactive console mode + con_non_interactive = !interactive; + + // to remember the current replay position when + // it is temporarily set to a scheduled command + char *curpos = NULL; + +restartwait: + + // execute commands until wait encountered + for (;;) { + + // restore position after scheduled command + if ( curpos != NULL ) { + data = curpos; + curpos = NULL; + } + + // check for execution of scheduled command + if ( num_scheduled_commands > 0 ) { + + if ( scheduled_commands[ 0 ].timestamp == demoinfo_curtime ) { + + // temporarily jump to position of scheduled command + curpos = data; + data = scheduled_commands[ 0 ].command; + + // remove this command from scheduled commands + if ( num_scheduled_commands > 1 ) { + size_t movesize = ( num_scheduled_commands - 1 ); + movesize *= sizeof( scheduled_command_s ); + memmove( &scheduled_commands[ 0 ], &scheduled_commands[ 1 ], movesize ); + } + num_scheduled_commands--; + } + } + + // for regular (non-scheduled) commands + if ( curpos == NULL ) { + + // exit loop on implied wait command + if ( scheduled_wait > 0 ) { + break; + } + + // count executed commands + demoinfo_curline++; + } + + // fetch command id + int actid = SWAP_32( *(int *)data ); + ASSERT( ( actid >= ACM_SIGNATURE ) && ( actid < ACM_NUM_COMMANDS ) ); + + // stop execution if end of command file reached + if ( actid == ACM_SIGNATURE ) { + bin_params = NULL; + con_non_interactive = FALSE; + return FALSE; + } + + data += sizeof( actid ); + bin_params = data; + + // exit loop on wait command + if ( actid == ACM_IDLEWAIT ) { + break; + } + + // check for packet replay + if ( action_commands[ actid ].flags & ACF_PACKETPARAM ) { + + // replay packet and get pointer advance + size_t advance = REC_PlayRemotePacketBin( (NetPacketExternal *) bin_params ); + + // check for invalid pointer advance ( -1 ... invalid packet ) + if ( advance == (size_t)-1 ) { + bin_params = NULL; + con_non_interactive = FALSE; + return FALSE; + } + + data += advance; + continue; + } + + // check for command scheduling + if ( action_commands[ actid ].flags & ACF_SCHEDPARAM ) { + // schedule command and advance pointer + data += ScheduleCommand( (int *) bin_params ); + continue; + } + + // determine how many parameter bytes need to be skipped. + // we do this before calling the action function because + // it might destroy its string parameter while parsing. + size_t paramsize = GetActionParamSize( actid, bin_params ); + + // call corresponding action function + // (it knows the type of its parameters) + ASSERT( action_commands[ actid ].func != NULL ); + (*action_commands[ actid ].func)(); + + // skip command's parameters (already read by action function) + data += paramsize; + } + + // wait command must not be scheduled + ASSERT( curpos == NULL ); + + // determine length of next wait interval + int waitcount; + if ( scheduled_wait > 0 ) { + + // completion of wait interval split by scheduled command + waitcount = scheduled_wait; + scheduled_wait = 0; + + } else { + + // preadvance over wait argument + data += sizeof( int32 ); + + // process wait + int32 suppliedwait; + if ( !AcFetchIntParams( 1, &suppliedwait ) ) { + + ASSERT( 0 ); + CON_AddLine( invalid_bin_wait ); + goto restartwait; + } + + waitcount = suppliedwait; + } + + // consume zero-waits transparently + if ( waitcount == 0 ) { + goto restartwait; + } + + ASSERT( waitcount > 0 ); + if ( waitcount < 0 ) { + CON_AddLine( invalid_bin_wait ); + goto restartwait; + } + + // check for scheduled commands in the middle of the next wait interval + if ( num_scheduled_commands > 0 ) { + ASSERT( demoinfo_curtime < scheduled_commands[ 0 ].timestamp ); + if ( demoinfo_curtime + waitcount > scheduled_commands[ 0 ].timestamp ) { + scheduled_wait = waitcount; + waitcount = scheduled_commands[ 0 ].timestamp - demoinfo_curtime; + scheduled_wait -= waitcount; + } + } + + // set duration to wait for + CurActionWait = waitcount; + + // remember for info + demoinfo_lastwait = (refframe_t) waitcount; + + // flag must be reset + con_non_interactive = FALSE; + + bin_params = NULL; + + return TRUE; +} + + +// save game state to current recording --------------------------------------- +// +void SaveGameState() +{ + //NOTE: + // this function is called by CON_EXT::StartRecording() to save + // the game state before a recording is started. + + AcSaveDataInfo(); +} + + +// include an entire demo file in the current compilation --------------------- +// +PRIVATE +int IncludeDemoFile( FILE *fp ) +{ + ASSERT( fp != NULL ); + + // read demo name + char *demoname; + if ( AcFetchStringParam( &demoname, TRUE ) ) { + + // open demo for inclusion + FILE *cpfp = DEMO_BinaryOpenDemo( demoname ); + if ( cpfp == NULL ) { + strcpy( paste_str, "demo file not found. (" ); + strcat( paste_str, demoname ); + strcat( paste_str, CON_FILE_COMPILED_EXTENSION ); + strcat( paste_str, ")" ); + CON_AddLine( paste_str ); + return TRUE; + } + + // skip header if present + DEMO_ParseDemoHeader( cpfp, -1, FALSE ); + + // demo will be copied in chunks + #define INCLUDE_BLOCK_SIZE 16384 + char *cpblock = (char *) ALLOCMEM( INCLUDE_BLOCK_SIZE ); + if ( cpblock == NULL ) + OUTOFMEM( 0 ); + + // paste in entire demo in chunks + size_t numread = 1; + while ( numread > 0 ) { + numread = fread( cpblock, 1, INCLUDE_BLOCK_SIZE, cpfp ); + if ( fwrite( cpblock, 1, numread, fp ) != numread ) { + CON_AddLine( compile_write_err ); + FREEMEM( cpblock ); + return FALSE; + } + } + + FREEMEM( cpblock ); + fclose( cpfp ); + + // strip off terminating eof marker + fseek( fp, -sizeof( int ), SEEK_CUR ); + } + + return TRUE; +} + + +// write int parameters of action command in binary format to file ------------ +// +PRIVATE +int WriteActionIntParams( FILE *fp, int paranum ) +{ + ASSERT( fp != NULL ); + ASSERT( paranum > 0 ); + + // write int parameters + int32 *intparams = (int32 *) ALLOCMEM( sizeof( int32 ) * paranum * 2 ); + int32 *intparams_swapped = &intparams[ paranum ]; + if ( AcFetchIntParams( paranum, intparams ) ) { + + // must be written in little-endian format + SwapParams_int( paranum, intparams, intparams_swapped ); + + if ( fwrite( intparams_swapped, sizeof( int32 ), paranum, fp ) != (unsigned int)paranum ) { + CON_AddLine( compile_write_err ); + FREEMEM( intparams ); + return FALSE; + } + + } else { + + CON_AddLine( compile_arg_inval ); + } + + FREEMEM( intparams ); + + return TRUE; +} + + +// write float parameters of action command in binary format to file ---------- +// +PRIVATE +int WriteActionFloatParams( FILE *fp, int paranum ) +{ + ASSERT( fp != NULL ); + ASSERT( paranum > 0 ); + + // write float parameters + hprec_t *floatparams = (hprec_t *) ALLOCMEM( sizeof( hprec_t ) * paranum * 2 ); + hprec_t *floatparams_swapped = &floatparams[ paranum ]; + if ( AcFetchFloatParams( paranum, floatparams ) ) { + + // must be written in little-endian format + SwapParams_hprec( paranum, floatparams, floatparams_swapped ); + + if ( fwrite( floatparams_swapped, sizeof( hprec_t ), paranum, fp ) != (unsigned int)paranum ) { + CON_AddLine( compile_write_err ); + FREEMEM( floatparams ); + return FALSE; + } + + } else { + + CON_AddLine( compile_arg_inval ); + } + + FREEMEM( floatparams ); + + return TRUE; +} + + +// write string parameter of action command in binary format to file ---------- +// +PRIVATE +int WriteActionStringParam( FILE *fp, dword flags ) +{ + ASSERT( fp != NULL ); + + // read string parameter + char *strparam; + if ( AcFetchStringParam( &strparam, ACF_EAT_SPACE( flags ) ) ) { + + unsigned int slen = strlen( strparam ) + 1; + if ( fwrite( strparam, 1, slen, fp ) != slen ) { + CON_AddLine( compile_write_err ); + return FALSE; + } + + } else { + + CON_AddLine( compile_arg_inval ); + } + + return TRUE; +} + + +// write packet parameter of action command in binary format to file ---------- +// +PRIVATE +int WriteActionPacketParam( FILE *fp ) +{ + ASSERT( fp != NULL ); + + int rc = TRUE; + + // read session and packet ids and fetch corresponding packet + int32 params[ 2 ]; + if ( AcFetchIntParams( 2, params ) ) { + + // fetch packet + NetPacketExternal* ext_gamepacket = (NetPacketExternal*) ALLOCMEM( RECORD_PACKET_SIZE ); + size_t psize = REC_FetchRemotePacket( ext_gamepacket, params[ 0 ], params[ 1 ] ); + + // write packet if valid + if ( psize > 0 ) { + if ( fwrite( ext_gamepacket, 1, psize, fp ) != psize ) { + CON_AddLine( compile_write_err ); + rc = FALSE; + } + } else { + CON_AddLine( compile_pkt_inval ); + rc = FALSE; + } + + FREEMEM( ext_gamepacket ); + + } else { + + CON_AddLine( compile_arg_inval ); + } + + return rc; +} + + +// forward declaration -------------------------------------------------------- +// +PRIVATE +void ExecActionCommand( char *cstr ); + + +// write a scheduled command into the current compilation --------------------- +// +PRIVATE +int WriteScheduledCommand( FILE *fp ) +{ + ASSERT( fp != NULL ); + + // prevent recursive call (scheduling of schedule command) + static int scheduled_command_writing_active = FALSE; + if ( scheduled_command_writing_active ) { + CON_AddLine( invalid_arg ); + return FALSE; + } + scheduled_command_writing_active = TRUE; + + // parse delta time parameter + char *timeparam = strtok( NULL, " " ); + if ( timeparam == NULL ) { + CON_AddLine( arg_missing ); + return FALSE; + } + + char *errpart; + int timedelta = strtol( timeparam, &errpart, int_calc_base ); + if ( *errpart != 0 ) { + CON_AddLine( invalid_arg ); + return FALSE; + } + + // write delta time in little-endian format + timedelta = SWAP_32( timedelta ); + if ( fwrite( &timedelta, sizeof( timedelta ), 1, fp ) != 1 ) { + CON_AddLine( compile_write_err ); + return FALSE; + } + + // append scheduled command as parameter after scheduling prefix + ExecActionCommand( NULL ); + + scheduled_command_writing_active = FALSE; + return TRUE; +} + + +// write action command in binary format to file ------------------------------ +// +PRIVATE +int WriteActionCommand( FILE *fp, int actid ) +{ + ASSERT( fp != NULL ); + ASSERT( actid > ACM_SIGNATURE ); + + dword flags = action_commands[ actid ].flags; + int paranum = action_commands[ actid ].numparameters; + + // exit if command may not be compiled + if ( ( flags & ACF_COMPILE ) == 0 ) { + CON_AddLine( compile_non_comp ); + return TRUE; + } + + // check for demo inclusion + // (command will be substituted) + if ( flags & ACF_DEMOPARAM ) { + return IncludeDemoFile( fp ); + } + + // must be written in little-endian format + actid = SWAP_32( actid ); + + // write id of command + if ( fwrite( &actid, sizeof( actid ), 1, fp ) != 1 ) { + CON_AddLine( compile_write_err ); + return FALSE; + } + + if ( flags & ACF_INTPARAMS ) { + + // write int parameters to file + if ( !WriteActionIntParams( fp, paranum ) ) { + return FALSE; + } + + } else if ( flags & ACF_FLOATPARAMS ) { + + // write float parameters to file + if ( !WriteActionFloatParams( fp, paranum ) ) { + return FALSE; + } + + } else if ( flags & ACF_STRINGPARAM ) { + + // write string parameter to file + ASSERT( paranum == 1 ); + if ( !WriteActionStringParam( fp, flags ) ) { + return FALSE; + } + + } else if ( flags & ACF_PACKETPARAM ) { + + // write packet parameter to file + if ( !WriteActionPacketParam( fp ) ) { + return FALSE; + } + + } else if ( flags & ACF_SCHEDPARAM ) { + + // write scheduled command to file + if ( !WriteScheduledCommand( fp ) ) { + return FALSE; + } + } + + return TRUE; +} + + +// call action function corresponding to action command or compile it --------- +// +INLINE +void CallActionFunction( int actid ) +{ + ASSERT( actid > ACM_SIGNATURE ); + + if ( compile_script ) { + + // if fp is NULL write error occurred earlier on + if ( compile_fp != NULL ) { + + // write command to file but do not execute it + if ( !WriteActionCommand( compile_fp, actid ) ) { + // write error cleanup + fclose( compile_fp ); + compile_fp = NULL; + } + } + + } else { + + // call corresponding action function + ASSERT( action_commands[ actid ].func != NULL ); + (*action_commands[ actid ].func)(); + } +} + + +// lookup action command and execute it --------------------------------------- +// +PRIVATE +void ExecActionCommand( char *cstr ) +{ + // scan table + char *aspec = strtok( cstr, " " ); + int aid = 0; + for ( aid = ACM_SIGNATURE + 1; ACMSTR( aid ) != NULL; aid++ ) { + + if ( strcmp( ACMSTR( aid ), aspec ) == 0 ) { + + dword flags = action_commands[ aid ].flags; + if ( ( action_commands[ aid ].func != NULL ) && + ( processing_batch || ( flags & ACF_DIRECT ) ) ) { + + CallActionFunction( aid ); + + } else { + + CON_AddLine( non_batch_use ); + } + break; + } + } + + if ( ACMSTR( aid ) == NULL ) { + + // no action command with specified name found + CON_AddLine( invalid_action ); + } +} + + +// exec action command (command prefixed with "ac.") -------------------------- +// +void ActionCommand( char *cstr ) +{ + ASSERT( cstr != NULL ); + + // exit if action commands currently not allowed + if ( preempt_action_commands ) { + CON_AddLine( action_preempted ); + return; + } + + char *bdot = cstr + ACMLEN( ACM_SIGNATURE ); + if ( *bdot != 0 ) { + + // look up command and execute it + ExecActionCommand( cstr ); + + } else { + + // no action specified after "ac." + CON_AddLine( no_action_found ); + } +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( CON_ACT ) +{ + // reset mapping table for class ids + int oldflag = AUX_DISABLE_CLASS_MAP_TABLE_RESET; + AUX_DISABLE_CLASS_MAP_TABLE_RESET = FALSE; + ResetClassMapTable(); + AUX_DISABLE_CLASS_MAP_TABLE_RESET = oldflag; +} + + + diff --git a/src/parsec/con_aux.cpp b/src/parsec/con_aux.cpp new file mode 100644 index 0000000..7b5e878 --- /dev/null +++ b/src/parsec/con_aux.cpp @@ -0,0 +1,429 @@ +/* + * PARSEC - Verbose Aux Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1998-2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// rendering subsystem +#include "r_patch.h" +#include "r_supp.h" + +// subsystem headers +#include "net_defs.h" + +// local module header +#include "con_aux.h" + +// proprietary module headers +#include "con_int.h" +#include "e_supp.h" +#include "net_rmev.h" + + +// flags +#define REGISTER_VERBOSE_AUX_COMMANDS +//#define EXCLUDE_SPECIAL_AUX_FLAGS +#define REGISTER_VERBOSE_AUX_DATA +//#define EXCLUDE_SPECIAL_AUX_DATA + + +//NOTE: +// this module is only loosely related to the CON_AUX.H +// header. that is, it may be omitted from linking +// entirely, if there should be no verbose aux commands. +// apart from this, project functionality will not be +// reduced. CON_AUX.H must always be part of the project. + + + +// perform remote event syncing for certain aux flags ------------------------- +// +#define DEF_RMEV_STATESYNC( f, k, v ) \ +PUBLIC \ +void RESync##f() \ +{ \ + if ( !NET_RmEvAllowed( RE_STATESYNC ) ) \ + return; \ + NET_RmEvStateSync( (k), (v) ); \ +} + + +DEF_RMEV_STATESYNC( NebulaId, RMEVSTATE_NEBULAID, AUXDATA_BACKGROUND_NEBULA_ID ) +DEF_RMEV_STATESYNC( Amazing, RMEVSTATE_AMAZING, AUXDATA_SKILL_AMAZING_TIME ) +DEF_RMEV_STATESYNC( Brilliant, RMEVSTATE_BRILLIANT, AUXDATA_SKILL_BRILLIANT_TIME ) +DEF_RMEV_STATESYNC( KillLimit, RMEVSTATE_KILLLIMIT, AUX_KILL_LIMIT_FOR_GAME_END ) + + +// flush texture cache after lod bias has been altered ------------------------ +// +PRIVATE +void FlushTexCache() +{ + if ( !TextModeActive ) { + + // flush entire texture cache + R_InvalidateCachedTexture( NULL ); + + // make sure texture data that might have been freed + // by the texture cache is available once again + ReloadFreedTextureBitmaps(); + + // precache textures + R_PrecacheTextures(); + } +} + + +// for registration of aux flags as integer variable commands ----------------- +// +PRIVATE +int_command_s verbose_aux_commands[] = { + + { 0x80, "aux_polygons_dont_fill_zbuffer", 0, 1, &AUX_POLYGONS_DONT_FILL_ZBUFFER, NULL, NULL }, + { 0x80, "aux_enable_gouraud_shading", 0, 1, &AUX_ENABLE_GOURAUD_SHADING, NULL, NULL }, + { 0x80, "aux_bsp_do_extended_sprod_check", 0, 1, &AUX_BSP_DO_EXTENDED_SPROD_CHECK, NULL, NULL }, + { 0x80, "aux_bsp_extcheck_draw_node", 0, 1, &AUX_BSP_EXTCHECK_DRAW_NODE, NULL, NULL }, + { 0x80, "aux_bsp_extcheck_backnode_first", 0, 1, &AUX_BSP_EXTCHECK_BACKNODE_FIRST, NULL, NULL }, + { 0x80, "aux_bsp_extcheck_skipsubtree", 0, 1, &AUX_BSP_EXTCHECK_SKIPSUBTREE, NULL, NULL }, + { 0x00, "aux_objctrl_disable_shipobjects", 0, 1, &AUX_OBJCTRL_DISABLE_SHIPOBJECTS, NULL, NULL }, + { 0x00, "aux_objctrl_disable_extraobjects", 0, 1, &AUX_OBJCTRL_DISABLE_EXTRAOBJECTS, NULL, NULL }, + { 0x00, "aux_objctrl_disable_laserobjects", 0, 1, &AUX_OBJCTRL_DISABLE_LASEROBJECTS, NULL, NULL }, + { 0x00, "aux_objctrl_disable_misslobjects", 0, 1, &AUX_OBJCTRL_DISABLE_MISSLOBJECTS, NULL, NULL }, + { 0x00, "aux_hud_show_changed_speed_number", 0, 1, &AUX_HUD_SHOW_CHANGED_SPEED_NUMBER, NULL, NULL }, + { 0x00, "aux_hud_show_changed_energy_number", 0, 1, &AUX_HUD_SHOW_CHANGED_ENERGY_NUMBER, NULL, NULL }, + { 0x00, "aux_hud_panel_3_control", 0, 2, &AUX_HUD_PANEL_3_CONTROL, NULL, NULL }, + { 0x00, "aux_hud_missile_bar_numbers", 0, 1, &AUX_HUD_MISSILE_BAR_NUMBERS, NULL, NULL }, + { 0x00, "aux_hud_panel_4_control", 0, 1, &AUX_HUD_PANEL_4_CONTROL, NULL, NULL }, + { 0x80, "aux_use_simple_explosion", 0, 1, &AUX_USE_SIMPLE_EXPLOSION, NULL, NULL }, + { 0x00, "aux_disable_console_say_output", 0, 1, &AUX_DISABLE_CONSOLE_SAY_OUTPUT, NULL, NULL }, + { 0x00, "aux_hud_disable_user_displays", 0, 1, &AUX_HUD_DISABLE_USER_DISPLAYS, NULL, NULL }, + { 0x00, "aux_dont_draw_blueprints", 0, 1, &AUX_DONT_DRAW_BLUEPRINTS, NULL, NULL }, + { 0x80, "aux_create_propulsion_fumes", 0, 1, &AUX_CREATE_PROPULSION_FUMES, NULL, NULL }, + { 0x80, "aux_disable_server_settings_button", 0, 1, &AUX_DISABLE_SERVER_SETTINGS_BUTTON, NULL, NULL }, + { 0x80, "aux_disable_server_menu_button", 0, 1, &AUX_DISABLE_SERVER_MENU_BUTTON, NULL, NULL }, + { 0x80, "aux_disable_zbuffer_clear", 0, 1, &AUX_DISABLE_ZBUFFER_CLEAR, NULL, NULL }, + { 0x80, "aux_disallow_usercontrolled_motion", 0, 1, &AUX_DISALLOW_USERCONTROLLED_MOTION, NULL, NULL }, + { 0x00, "aux_disable_soundeffects", 0, 1, &AUX_DISABLE_SOUNDEFFECTS, NULL, NULL }, + { 0x80, "aux_disable_cleardemo_on_repstop", 0, 1, &AUX_DISABLE_CLEARDEMO_ON_REPSTOP, NULL, NULL }, + { 0x80, "aux_display_rate_in_viewers", 0, 1, &AUX_DISPLAY_RATE_IN_VIEWERS, NULL, NULL }, + { 0x00, "aux_awaitretrace_on_framefinish", 0, 1, &AUX_AWAITRETRACE_ON_FRAMEFINISH, NULL, NULL }, + { 0x00, "aux_disable_fixed_star_rendering", 0, 1, &AUX_DISABLE_FIXED_STAR_RENDERING, NULL, NULL }, + { 0x00, "aux_disable_pseudo_star_rendering", 0, 1, &AUX_DISABLE_PSEUDO_STAR_RENDERING, NULL, NULL }, + { 0x80, "aux_disable_flashwhite_on_gameentrY", 0, 1, &AUX_DISABLE_FLASHWHITE_ON_GAMEENTRY, NULL, NULL }, + { 0x80, "aux_wait_for_keypress_after_fadein", 0, 1, &AUX_WAIT_FOR_KEYPRESS_AFTER_FADEIN, NULL, NULL }, + { 0x80, "aux_disable_reortho_camera_in_game", 0, 1, &AUX_DISABLE_REORTHO_CAMERA_IN_GAME, NULL, NULL }, + { 0x80, "aux_disable_reortho_in_viewers", 0, 1, &AUX_DISABLE_REORTHO_IN_VIEWERS, NULL, NULL }, + { 0x80, "aux_dont_cull_particle_objects", 0, 1, &AUX_DONT_CULL_PARTICLE_OBJECTS, NULL, NULL }, + { 0x00, "aux_disable_particle_system", 0, 1, &AUX_DISABLE_PARTICLE_SYSTEM, NULL, NULL }, + { 0x00, "aux_enable_texture_overloading", 0, 1, &AUX_ENABLE_TEXTURE_OVERLOADING, NULL, NULL }, + { 0x00, "aux_enable_object_overloading", 0, 1, &AUX_ENABLE_OBJECT_OVERLOADING, NULL, NULL }, + { 0x00, "aux_enable_bitmap_overloading", 0, 1, &AUX_ENABLE_BITMAP_OVERLOADING, NULL, NULL }, + { 0x80, "aux_disable_polygon_mipmapping", 0, 1, &AUX_DISABLE_POLYGON_MIPMAPPING, NULL, NULL }, + { 0x80, "aux_disable_bitmap_mipmapping", 0, 1, &AUX_DISABLE_BITMAP_MIPMAPPING, NULL, NULL }, + { 0x80, "aux_disable_polygon_filtering", 0, 1, &AUX_DISABLE_POLYGON_FILTERING, NULL, NULL }, + { 0x80, "aux_disable_bitmap_filtering", 0, 1, &AUX_DISABLE_BITMAP_FILTERING, NULL, NULL }, + { 0x00, "aux_enable_panoramic_background", 0, 1, &AUX_ENABLE_PANORAMIC_BACKGROUND, NULL, NULL }, + { 0x00, "aux_disable_panoramic_layer_1", 0, 1, &AUX_DISABLE_PANORAMIC_LAYER_1, NULL, NULL }, + { 0x00, "aux_disable_panoramic_layer_2", 0, 1, &AUX_DISABLE_PANORAMIC_LAYER_2, NULL, NULL }, + { 0x00, "aux_disable_panoramic_layer_3", 0, 1, &AUX_DISABLE_PANORAMIC_LAYER_3, NULL, NULL }, + { 0x80, "aux_disable_texture_wrapping", 0, 1, &AUX_DISABLE_TEXTURE_WRAPPING, NULL, NULL }, + { 0x80, "aux_disable_buffer_clear", 0, 1, &AUX_DISABLE_BUFFER_CLEAR, NULL, NULL }, + { 0x80, "aux_spreadfire_particles_extinfo", 0, 1, &AUX_SPREADFIRE_PARTICLES_EXTINFO, NULL, NULL }, + { 0x80, "aux_lightning_particles_extinfo", 0, 1, &AUX_LIGHTNING_PARTICLES_EXTINFO, NULL, NULL }, + { 0x80, "aux_explosion_particles_extinfo", 0, 1, &AUX_EXPLOSION_PARTICLES_EXTINFO, NULL, NULL }, + { 0x80, "aux_energyfield_particles_extinfo", 0, 1, &AUX_ENERGYFIELD_PARTICLES_EXTINFO, NULL, NULL }, + { 0x80, "aux_protshield_particles_extinfo", 0, 1, &AUX_PROTSHIELD_PARTICLES_EXTINFO, NULL, NULL }, + { 0x80, "aux_megashield_particles_extinfo", 0, 1, &AUX_MEGASHIELD_PARTICLES_EXTINFO, NULL, NULL }, + { 0x00, "aux_dont_flash_screen_on_flare", 0, 1, &AUX_DONT_FLASH_SCREEN_ON_FLARE, NULL, NULL }, + { 0x00, "aux_dont_draw_flare_circles", 0, 1, &AUX_DONT_DRAW_FLARE_CIRCLES, NULL, NULL }, + { 0x00, "aux_disable_screenshot_message", 0, 1, &AUX_DISABLE_SCREENSHOT_MESSAGE, NULL, NULL }, + { 0x80, "aux_disable_floatlogo_rotation", 0, 1, &AUX_DISABLE_FLOATLOGO_ROTATION, NULL, NULL }, + { 0x80, "aux_verbose_texture_mem_manager", 0, 1, &AUX_VERBOSE_TEXTURE_MEM_MANAGER, NULL, NULL }, + { 0x80, "aux_disable_object_depth_sort", 0, 1, &AUX_DISABLE_OBJECT_DEPTH_SORT, NULL, NULL }, + { 0x80, "aux_enable_console_debug_messages", 0, 1, &AUX_ENABLE_CONSOLE_DEBUG_MESSAGES, NULL, NULL }, + { 0x80, "aux_enable_console_message_log", 0, 15, &AUX_ENABLE_CONSOLE_MESSAGE_LOG, NULL, NULL }, + { 0x80, "aux_record_packets_into_session", 0, 1, &AUX_RECORD_PACKETS_INTO_SESSION, NULL, NULL }, + { 0x80, "aux_create_extras_during_replay", 0, 1, &AUX_CREATE_EXTRAS_DURING_REPLAY, NULL, NULL }, + { 0x80, "aux_disable_absolute_recording", 0, 1, &AUX_DISABLE_ABSOLUTE_RECORDING, NULL, NULL }, + { 0x80, "aux_record_verbose_packets", 0, 1, &AUX_RECORD_VERBOSE_PACKETS, NULL, NULL }, + { 0x00, "aux_perform_automatic_connect", 0, 1, &AUX_PERFORM_AUTOMATIC_CONNECT, NULL, NULL }, + { 0x80, "aux_disable_replay_net_simulation", 0, 1, &AUX_DISABLE_REPLAY_NET_SIMULATION, NULL, NULL }, + { 0x00, "aux_disable_local_stargate", 0, 1, &AUX_DISABLE_LOCAL_STARGATE, NULL, NULL }, + { 0x80, "aux_particle_base_explosion", 0, 1, &AUX_PARTICLE_BASE_EXPLOSION, NULL, NULL }, + { 0x80, "aux_no_delayed_join_replay", 0, 1, &AUX_NO_DELAYED_JOIN_REPLAY, NULL, NULL }, + { 0x00, "aux_hud_enable_packet_loss_meter", 0, 1, &AUX_HUD_ENABLE_PACKET_LOSS_METER, NULL, NULL }, + { 0x80, "aux_packetdrop_testing", 0, 100, &AUX_PACKETDROP_TESTING, NULL, NULL }, + { 0x00, "aux_disable_talk_escape_on_tab", 0, 1, &AUX_DISABLE_TALK_ESCAPE_ON_TAB, NULL, NULL }, + { 0x00, "aux_use_big_font_in_message_area", 0, 1, &AUX_USE_BIG_FONT_IN_MESSAGE_AREA, NULL, NULL }, + { 0x00, "aux_hud_disable_nonbasic_displays", 0, 1, &AUX_HUD_DISABLE_NONBASIC_DISPLAYS, NULL, NULL }, + { 0x80, "aux_hud_enable_debuginfo", 0, 1, &AUX_HUD_ENABLE_DEBUGINFO, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_memory", 0, 1, &AUX_HUD_DEBUGINFO_MEMORY, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_objects", 0, 1, &AUX_HUD_DEBUGINFO_OBJECTS, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_position", 0, 1, &AUX_HUD_DEBUGINFO_POSITION, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_packets", 0, 1, &AUX_HUD_DEBUGINFO_PACKETS, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_geometry", 0, 1, &AUX_HUD_DEBUGINFO_GEOMETRY, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_rasterization", 0, 1, &AUX_HUD_DEBUGINFO_RASTERIZATION, NULL, NULL }, + { 0x80, "aux_advanced_playerinterpolation", 0, 3, &AUX_ADVANCED_PLAYERINTERPOLATION, NULL, NULL }, + { 0x80, "aux_save_persistent_intcommands", 0, 1, &AUX_SAVE_PERSISTENT_INTCOMMANDS, NULL, NULL }, + { 0x80, "aux_save_persistent_usrcommands", 0, 1, &AUX_SAVE_PERSISTENT_USRCOMMANDS, NULL, NULL }, + { 0x80, "aux_save_persistent_aux_array", 0, 1, &AUX_SAVE_PERSISTENT_AUX_ARRAY, NULL, NULL }, + { 0x00, "aux_disable_rc_script_saving", 0, 1, &AUX_DISABLE_RC_SCRIPT_SAVING, NULL, NULL }, + { 0x00, "aux_force_workdir_to_current", 0, 1, &AUX_FORCE_WORKDIR_TO_CURRENT, NULL, NULL }, + { 0x00, "aux_force_filepath_to_current", 0, 1, &AUX_FORCE_FILEPATH_TO_CURRENT, NULL, NULL }, + { 0x80, "aux_disable_dead_reckoning", 0, 1, &AUX_DISABLE_DEAD_RECKONING, NULL, NULL }, + { 0x00, "aux_redirect_talk_to_irc_server", 0, 1, &AUX_REDIRECT_TALK_TO_IRC_SERVER, NULL, NULL }, + { 0x80, "aux_hud_debuginfo_over_console", 0, 1, &AUX_HUD_DEBUGINFO_OVER_CONSOLE, NULL, NULL }, + { 0x80, "aux_explosion_draw_shockwave", 0, 3, &AUX_EXPLOSION_DRAW_SHOCKWAVE, NULL, NULL }, + { 0x80, "aux_cmd_write_active_in_textmode", 0, 1, &AUX_CMD_WRITE_ACTIVE_IN_TEXTMODE, NULL, NULL }, + { 0x80, "aux_enable_volumetric_clouds", 0, 1, &AUX_ENABLE_VOLUMETRIC_CLOUDS, NULL, NULL }, + { 0x80, "aux_small_particle_triangles", 0, 256, &AUX_SMALL_PARTICLE_TRIANGLES, NULL, NULL }, + { 0x80, "aux_obj_sort_polys_on_texture", 0, 1, &AUX_OBJ_SORT_POLYS_ON_TEXTURE, NULL, NULL }, + { 0x80, "aux_no_default_rasterizer_state", 0, 1, &AUX_NO_DEFAULT_RASTERIZER_STATE, NULL, NULL }, + { 0x80, "aux_allow_only_texture_loading", 0, 1, &AUX_ALLOW_ONLY_TEXTURE_LOADING, NULL, NULL }, + { 0x80, "aux_cmd_write_disable_output", 0, 1, &AUX_CMD_WRITE_DISABLE_OUTPUT, NULL, NULL }, + { 0x80, "aux_attach_object_particles", 0, 1, &AUX_ATTACH_OBJECT_PARTICLES, NULL, NULL }, + { 0x80, "aux_stop_demo_replay_on_connect", 0, 1, &AUX_STOP_DEMO_REPLAY_ON_CONNECT, NULL, NULL }, + { 0x80, "aux_disable_disconnect_button", 0, 1, &AUX_DISABLE_DISCONNECT_BUTTON, NULL, NULL }, + { 0x00, "aux_enable_sample_overloading", 0, 1, &AUX_ENABLE_SAMPLE_OVERLOADING, NULL, NULL }, + { 0x80, "aux_enable_shader_overloading", 0, 1, &AUX_ENABLE_SHADER_OVERLOADING, NULL, NULL }, + { 0x80, "aux_attach_thrust_objects", 0, 1, &AUX_ATTACH_THRUST_OBJECTS, NULL, NULL }, + { 0x80, "aux_disable_genobject_particles", 0, 1, &AUX_DISABLE_GENOBJECT_PARTICLES, NULL, NULL }, + { 0x80, "aux_autostart_backgroundplayer", 0, 1, &AUX_AUTOSTART_BACKGROUNDPLAYER, NULL, NULL }, + { 0x80, "aux_hud_advanced_killstats", 0, 1, &AUX_HUD_ADVANCED_KILLSTATS, NULL, NULL }, + { 0x80, "aux_disable_package_scripts", 0, 1, &AUX_DISABLE_PACKAGE_SCRIPTS, NULL, NULL }, + { 0x80, "aux_enable_killed_ship_extras", 0, 1, &AUX_ENABLE_KILLED_SHIP_EXTRAS, NULL, NULL }, + { 0x80, "aux_stop_at_end_of_cd_track", 0, 1, &AUX_STOP_AT_END_OF_CD_TRACK, NULL, NULL }, + { 0x80, "aux_direct_cluster_rendering", 0, 1, &AUX_DIRECT_CLUSTER_RENDERING, NULL, NULL }, + { 0x00, "aux_enable_elite_radar", 0, 1, &AUX_ENABLE_ELITE_RADAR, NULL, NULL }, + { 0x80, "aux_draw_missiles_on_radar", 0, 1, &AUX_DRAW_MISSILES_ON_RADAR, NULL, NULL }, + { 0x00, "aux_draw_cockpit", 0, 1, &AUX_DRAW_COCKPIT, NULL, NULL }, + { 0x00, "aux_draw_cockpit_damage", 0, 1, &AUX_DRAW_COCKPIT_DAMAGE, NULL, NULL }, + { 0x00, "aux_draw_cockpit_weapons", 0, 1, &AUX_DRAW_COCKPIT_WEAPONS, NULL, NULL }, + { 0x00, "aux_draw_cockpit_radar", 0, 1, &AUX_DRAW_COCKPIT_RADAR, NULL, NULL }, + { 0x00, "aux_draw_cockpit_iconbar", 0, 1, &AUX_DRAW_COCKPIT_ICONBAR, NULL, NULL }, + { 0x80, "aux_objctrl_disable_customobjects", 0, 1, &AUX_OBJCTRL_DISABLE_CUSTOMOBJECTS, NULL, NULL }, + { 0x80, "aux_draw_cockpit_crosshair", 0, 2, &AUX_DRAW_COCKPIT_CROSSHAIR, NULL, NULL }, + { 0x80, "aux_enable_customobject_huddisplay", 0, 1, &AUX_ENABLE_CUSTOMOBJECT_HUDDISPLAY, NULL, NULL }, + { 0x80, "aux_draw_stargates_on_radar", 0, 1, &AUX_DRAW_STARGATES_ON_RADAR, NULL, NULL }, + { 0x80, "aux_enable_cockpit_swaying", 0, 2, &AUX_ENABLE_COCKPIT_SWAYING, NULL, NULL }, + { 0x80, "aux_enable_cockpit_rattling", 0, 1, &AUX_ENABLE_COCKPIT_RATTLING, NULL, NULL }, + { 0x80, "aux_enable_smooth_ship_control", 0, 1, &AUX_ENABLE_SMOOTH_SHIP_CONTROL, NULL, NULL }, + { 0x80, "aux_enable_extended_target_caret", 0, 1, &AUX_ENABLE_EXTENDED_TARGET_CARET, NULL, NULL }, + { 0x00, "aux_show_ping_in_serverlist", 0, 1, &AUX_SHOW_PING_IN_SERVERLIST, NULL, NULL }, + { 0x00, "aux_draw_cockpit_iconbar_background", 0, 1, &AUX_DRAW_COCKPIT_ICONBAR_BACKGROUND, NULL, NULL }, + { 0x80, "aux_enable_missile_propulsion_fumes", 0, 3, &AUX_ENABLE_MISSILE_PROPULSION_FUMES, NULL, NULL }, + { 0x80, "aux_laserbeam_instead_of_laser", 0, 1, &AUX_LASERBEAM_INSTEAD_OF_LASER, NULL, NULL }, + { 0x80, "aux_enable_free_camera", 0, 1, &AUX_ENABLE_FREE_CAMERA, NULL, NULL }, + { 0x80, "aux_flagword_screenshot_helpers", 0, 255, &AUX_FLAGWORD_SCREENSHOT_HELPERS, NULL, NULL }, + { 0x80, "aux_display_remote_join_object_id", 0, 1, &AUX_DISPLAY_REMOTE_JOIN_OBJECT_ID, NULL, NULL }, + { 0x00, "aux_enable_refframe_timeplot", 0, 1, &AUX_ENABLE_REFFRAME_TIMEPLOT, NULL, NULL }, + { 0x80, "aux_disable_nearplane_touch_culling", 0, 1, &AUX_DISABLE_NEARPLANE_TOUCH_CULLING, NULL, NULL }, + { 0x00, "aux_disable_msgarea_if_console_open", 0, 1, &AUX_DISABLE_MSGAREA_IF_CONSOLE_OPEN, NULL, NULL }, + { 0x80, "aux_enable_missile_polygon_trails", 0, 3, &AUX_ENABLE_MISSILE_POLYGON_TRAILS, NULL, NULL }, + { 0x00, "aux_enable_funky_audio_comments", 0, 1, &AUX_ENABLE_FUNKY_AUDIO_COMMENTS, NULL, NULL }, + { 0x00, "aux_disable_package_script_listing", 0, 1, &AUX_DISABLE_PACKAGE_SCRIPT_LISTING, NULL, NULL }, + { 0x00, "aux_disable_demo_replay_in_menu", 0, 1, &AUX_DISABLE_DEMO_REPLAY_IN_MENU, NULL, NULL }, + { 0x80, "aux_no_delayed_create_object_replay", 0, 1, &AUX_NO_DELAYED_CREATE_OBJECT_REPLAY, NULL, NULL }, + { 0x80, "aux_disable_sorted_playerlist", 0, 1, &AUX_DISABLE_SORTED_PLAYERLIST, NULL, NULL }, + { 0x80, "aux_disable_object_free_on_cleardemo", 0, 1, &AUX_DISABLE_OBJECT_FREE_ON_CLEARDEMO, NULL, NULL }, + { 0x80, "aux_enable_demo_replay_info_display", 0, 1, &AUX_ENABLE_DEMO_REPLAY_INFO_DISPLAY, NULL, NULL }, + { 0x80, "aux_disable_joystick_throttle", 0, 1, &AUX_DISABLE_JOYSTICK_THROTTLE, NULL, NULL }, + { 0x80, "aux_disable_package_data_files", 0, 1, &AUX_DISABLE_PACKAGE_DATA_FILES, NULL, NULL }, + { 0x80, "aux_dont_overload_texture_geometry", 0, 1, &AUX_DONT_OVERLOAD_TEXTURE_GEOMETRY, NULL, NULL }, + { 0x80, "aux_enable_game_status_window", 0, 1, &AUX_ENABLE_GAME_STATUS_WINDOW, NULL, NULL }, + { 0x80, "aux_disable_quit_button", 0, 1, &AUX_DISABLE_QUIT_BUTTON, NULL, NULL }, + { 0x80, "aux_disable_message_area", 0, 1, &AUX_DISABLE_MESSAGE_AREA, NULL, NULL }, + { 0x80, "aux_enable_demo_replay_user_input", 0, 1, &AUX_ENABLE_DEMO_REPLAY_USER_INPUT, NULL, NULL }, + { 0x80, "aux_disable_user_gameloop_exit", 0, 1, &AUX_DISABLE_USER_GAMELOOP_EXIT, NULL, NULL }, + { 0x80, "aux_disable_floating_menu_drawing", 0, 1, &AUX_DISABLE_FLOATING_MENU_DRAWING, NULL, NULL }, + { 0x80, "aux_save_aux_array_on_demo_replay", 0, 1, &AUX_SAVE_AUX_ARRAY_ON_DEMO_REPLAY, NULL, NULL }, + { 0x80, "aux_save_aux_array_on_demo_record", 0, 1, &AUX_SAVE_AUX_ARRAY_ON_DEMO_RECORD, NULL, NULL }, + { 0x80, "aux_save_player_name_on_demo_replay", 0, 1, &AUX_SAVE_PLAYER_NAME_ON_DEMO_REPLAY, NULL, NULL }, + { 0x80, "aux_kill_limit_for_game_end", 0, 99, &AUX_KILL_LIMIT_FOR_GAME_END, RESyncKillLimit, NULL }, + { 0x80, "aux_disable_join_game_button", 0, 1, &AUX_DISABLE_JOIN_GAME_BUTTON, NULL, NULL }, + { 0x80, "aux_kill_limit_reset_on_game_end", 0, 1, &AUX_KILL_LIMIT_RESET_ON_GAME_END, NULL, NULL }, + { 0x80, "aux_enable_joystick_binding", 0, 1, &AUX_ENABLE_JOYSTICK_BINDING, NULL, NULL }, + { 0x80, "aux_enable_depthcued_radar_dots", 0, 1, &AUX_ENABLE_DEPTHCUED_RADAR_DOTS, NULL, NULL }, + { 0x80, "aux_enable_mouse_for_menu_screens", 0, 1, &AUX_ENABLE_MOUSE_FOR_MENU_SCREENS, NULL, NULL }, +#ifdef ENABLE_CHEAT_COMMANDS + { 0x80, "aux_cheat_disable_ammo_checks", 0, 1, &AUX_CHEAT_DISABLE_AMMO_CHECKS, NULL, NULL }, + { 0x80, "aux_cheat_disable_energy_checks", 0, 1, &AUX_CHEAT_DISABLE_ENERGY_CHECKS, NULL, NULL }, + { 0x80, "aux_cheat_disable_device_checks", 0, 1, &AUX_CHEAT_DISABLE_DEVICE_CHECKS, NULL, NULL }, +#endif // ENABLE_CHEAT_COMMANDS + { 0x80, "aux_draw_wireframe", 0, 2, &AUX_DRAW_WIREFRAME, NULL, NULL }, + { 0x80, "aux_draw_normals", 0, 1, &AUX_DRAW_NORMALS, NULL, NULL }, + { 0x80, "aux_enable_lighting_types", 0, 0xf, &AUX_ENABLE_LIGHTING_TYPES, NULL, NULL }, + { 0x80, "aux_enable_colanim_overloading", 0, 1, &AUX_ENABLE_COLANIM_OVERLOADING, NULL, NULL }, + { 0x00, "aux_enable_trilinear_filtering", 0, 1, &AUX_ENABLE_TRILINEAR_FILTERING, NULL, NULL, 1 }, + { 0x00, "aux_enable_movie_writing", 0, 1, &AUX_ENABLE_MOVIE_WRITING, NULL, NULL }, + { 0x00, "aux_enable_volumetric_fog", 0, 1, &AUX_ENABLE_VOLUMETRIC_FOG, NULL, NULL }, + { 0x00, "aux_enable_max_display_freq", 0, 1, &AUX_ENABLE_MAX_DISPLAY_FREQ, NULL, NULL }, + { 0x00, "aux_enable_fov_control", 0, 1, &AUX_ENABLE_FOV_CONTROL, NULL, NULL, 1 }, + { 0x00, "aux_allow_cache_texture_evict", 0, 1, &AUX_ALLOW_CACHE_TEXTURE_EVICT, NULL, NULL }, + { 0x80, "aux_disable_clear_text_on_cleardemo", 0, 1, &AUX_DISABLE_CLEAR_TEXT_ON_CLEARDEMO, NULL, NULL }, + { 0x80, "aux_disable_class_map_table_reset", 0, 1, &AUX_DISABLE_CLASS_MAP_TABLE_RESET, NULL, NULL }, + { 0x80, "aux_save_refframefreq_on_demo_replay", 0, 1, &AUX_SAVE_REFFRAMEFREQ_ON_DEMO_REPLAY, NULL, NULL }, + { 0x80, "aux_save_lightingconf_on_demo_replay", 0, 1, &AUX_SAVE_LIGHTINGCONF_ON_DEMO_REPLAY, NULL, NULL }, + { 0x80, "aux_enable_multiple_texture_units", 0, 1, &AUX_ENABLE_MULTIPLE_TEXTURE_UNITS, NULL, NULL }, + { 0x80, "aux_disable_camfilt_reset_on_cleardemo", 0, 1, &AUX_DISABLE_CAMFILT_RESET_ON_CLEARDEMO, NULL, NULL }, + { 0x80, "aux_disable_dying_ship_movement", 0, 1, &AUX_DISABLE_DYING_SHIP_MOVEMENT, NULL, NULL }, + { 0x80, "aux_disable_panel_decorations", 0, 1, &AUX_DISABLE_PANEL_DECORATIONS, NULL, NULL }, + { 0x80, "aux_disable_kills_left_announcement", 0, 1, &AUX_DISABLE_KILLS_LEFT_ANNOUNCEMENT, NULL, NULL }, + { 0x80, "aux_disable_automatic_nebula_lighting", 0, 1, &AUX_DISABLE_AUTOMATIC_NEBULA_LIGHTING, NULL, NULL }, + { 0x80, "aux_disable_backgroundplayer_item_fill", 0, 1, &AUX_DISABLE_BACKGROUNDPLAYER_ITEM_FILL, NULL, NULL }, + { 0x80, "aux_draw_planets_on_radar", 0, 1, &AUX_DRAW_PLANETS_ON_RADAR, NULL, NULL }, + { 0x80, "aux_draw_server_ping", 0, 1, &AUX_DRAW_SERVER_PING, NULL, NULL }, + { 0x80, "aux_disable_point_visibility_detection", 0, 1, &AUX_DISABLE_POINT_VISIBILITY_DETECTION, NULL, NULL }, + { 0x80, "aux_enable_texture_precaching", 0, 1, &AUX_ENABLE_TEXTURE_PRECACHING, NULL, NULL }, + { 0x80, "aux_disable_level_sync", 0, 1, &AUX_DISABLE_LEVEL_SYNC , NULL, NULL }, + { 0x80, "aux_draw_teleporters_on_radar", 0, 1, &AUX_DRAW_TELEPORTERS_ON_RADAR, NULL, NULL }, + { 0x80, "aux_disable_level_console_messages", 0, 1, &AUX_DISABLE_LEVEL_CONSOLE_MESSAGES, NULL, NULL }, + { 0x80, "aux_nebula_flags", 0, 16, &AUX_NEBULA_FLAGS, NULL, NULL }, + { 0x80, "aux_netcode_flags", 0, 64, &AUX_NETCODE_FLAGS, NULL, NULL }, + { 0x80, "aux_enable_beep_on_recv", 0, 1, &AUX_ENABLE_BEEP_ON_RECV, NULL, NULL }, + { 0x80, "aux_debug_netstream_dump", 0, 15, &AUX_DEBUG_NETSTREAM_DUMP, NULL, NULL }, + { 0x80, "aux_anisotropic_filtering", 0, 16, &AUX_ANISOTROPIC_FILTERING, NULL, NULL }, + { 0x80, "aux_msaa", 0, 8, &AUX_MSAA, NULL, NULL }, +}; + +#define NUM_VERBOSE_AUX_COMMANDS CALC_NUM_ARRAY_ENTRIES( verbose_aux_commands ) + + +// for registration of aux data as integer variable commands ------------------ +// +PRIVATE +int_command_s verbose_aux_data[] = { + + { 0x80, "auxdata_least_vertex_1_over_z", 0, 0, &AUXDATA_LEAST_VERTEX_1_OVER_Z, NULL, NULL }, + { 0x80, "auxdata_greatest_vertex_1_over_z", 0, 0, &AUXDATA_GREATEST_VERTEX_1_OVER_Z, NULL, NULL }, + { 0x80, "auxdata_fillzbuffer_was_called", 0, 0, &AUXDATA_FILLZBUFFER_WAS_CALLED, NULL, NULL }, + { 0x80, "auxdata_bsp_scalarproduct_value", 0, 0, &AUXDATA_BSP_SCALARPRODUCT_VALUE, NULL, NULL }, + { 0x80, "auxdata_bsp_error_eps", 0, 0, &AUXDATA_BSP_ERROR_EPS, NULL, NULL }, + { 0x80, "auxdata_bsp_backface_tolerance_eps", 0, 0, &AUXDATA_BSP_BACKFACE_TOLERANCE_EPS, NULL, NULL }, + { 0x80, "auxdata_lensflare_center_pixel", 0, 0, &AUXDATA_LENSFLARE_CENTER_PIXEL, NULL, NULL }, + { 0x00, "auxdata_num_particle_clusters", 0, 0, &AUXDATA_NUM_PARTICLE_CLUSTERS, NULL, NULL }, + { 0x00, "auxdata_num_visible_pclusters", 0, 0, &AUXDATA_NUM_VISIBLE_PCLUSTERS, NULL, NULL }, + { 0x00, "auxdata_psphere_creation_code", 0, 0, &AUXDATA_PSPHERE_CREATION_CODE, NULL, NULL }, + { 0x00, "auxdata_psphere_radius", 0, 0, &AUXDATA_PSPHERE_RADIUS, NULL, NULL }, + { 0x00, "auxdata_psphere_type", 0, 0, &AUXDATA_PSPHERE_TYPE, NULL, NULL }, + { 0x00, "auxdata_tmm_next_texmem_location", 0, 0, &AUXDATA_TMM_NEXT_TEXMEM_LOCATION, NULL, NULL }, + { 0x00, "auxdata_tmm_num_downloaded", 0, 0, &AUXDATA_TMM_NUM_DOWNLOADED, NULL, NULL }, + { 0x00, "auxdata_tmm_num_nondiscardable", 0, 0, &AUXDATA_TMM_NUM_NONDISCARDABLE, NULL, NULL }, + { 0x00, "auxdata_tmm_num_hashtable_entries", 0, 0, &AUXDATA_TMM_NUM_HASHTABLE_ENTRIES, NULL, NULL }, + { 0x00, "auxdata_tmm_cur_tailbubble_size", 0, 0, &AUXDATA_TMM_CUR_TAILBUBBLE_SIZE, NULL, NULL }, + { 0x00, "auxdata_tmm_cur_bubble_size", 0, 0, &AUXDATA_TMM_CUR_BUBBLE_SIZE, NULL, NULL }, + { 0x00, "auxdata_tmm_mipmap_lod_bias", 0, 8, &AUXDATA_TMM_MIPMAP_LOD_BIAS, FlushTexCache, NULL }, + { 0x00, "auxdata_screenshot_format", 0, 2, &AUXDATA_SCREENSHOT_FORMAT, NULL, NULL }, + { 0x00, "auxdata_screenshot_subformat", 0, 1, &AUXDATA_SCREENSHOT_SUBFORMAT, NULL, NULL }, + { 0x00, "auxdata_movie_format", 0, 2, &AUXDATA_MOVIE_FORMAT, NULL, NULL }, + { 0x00, "auxdata_movie_subformat", 0, 1, &AUXDATA_MOVIE_SUBFORMAT, NULL, NULL }, + { 0x00, "auxdata_message_lifetime", 100, 10000, &AUXDATA_MESSAGE_LIFETIME, NULL, NULL }, + { 0x00, "auxdata_message_area_size", 0, MAX_SCREENMESSAGES, &AUXDATA_MESSAGE_AREA_SIZE, NULL, NULL }, + { 0x80, "auxdata_mouse_sensitivity", 1, 100, &AUXDATA_MOUSE_SENSITIVITY, NULL, NULL }, + { 0x80, "auxdata_playerlerp_transition_time", 0, 2000,&AUXDATA_PLAYERLERP_TRANSITION_TIME, NULL, NULL }, + { 0x00, "auxdata_lod_discrete_geometry_bias", 0, 5, &AUXDATA_LOD_DISCRETE_GEOMETRY_BIAS, NULL, NULL }, + { 0x00, "auxdata_smooth_ship_control_factor", 0, 1000,&AUXDATA_SMOOTH_SHIP_CONTROL_FACTOR, NULL, NULL }, + { 0x00, "auxdata_background_nebula_id", 0, 6, &AUXDATA_BACKGROUND_NEBULA_ID, RESyncNebulaId, NULL }, + { 0x00, "auxdata_skill_amazing_time", 0, 6000,&AUXDATA_SKILL_AMAZING_TIME, RESyncAmazing, NULL }, + { 0x00, "auxdata_skill_brilliant_time", 0, 6000,&AUXDATA_SKILL_BRILLIANT_TIME, RESyncBrilliant, NULL }, + { 0x00, "auxdata_last_soundsys_returncode", 0, 0, &AUXDATA_LAST_SOUNDSYS_RETURNCODE, NULL, NULL }, + { 0x00, "auxdata_numremplayers_copy", 0, 0, &AUXDATA_NUMREMPLAYERS_COPY, NULL, NULL }, + +}; + +#define NUM_VERBOSE_AUX_DATA CALC_NUM_ARRAY_ENTRIES( verbose_aux_data ) + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( CON_AUX ) +{ + ASSERT( NUM_VERBOSE_AUX_COMMANDS <= AUX_ARRAY_NUM_ENTRIES_USED ); + ASSERT( NUM_VERBOSE_AUX_DATA <= AUXDATA_ARRAY_NUM_ENTRIES_USED ); + +#ifdef REGISTER_VERBOSE_AUX_COMMANDS + + // register aux flags + for ( unsigned int caux = 0; caux < NUM_VERBOSE_AUX_COMMANDS; caux++ ) { + + //NOTE: + // bit 7 of the persistence field is used to denote + // special aux flags that may be excluded from registration. + + #ifdef EXCLUDE_SPECIAL_AUX_FLAGS + + if ( verbose_aux_commands[ caux ].persistence & 0x80 ) + continue; + + #endif + + // destructive but doesn't matter here + verbose_aux_commands[ caux ].persistence &= ~0x80; + + CON_RegisterIntCommand( verbose_aux_commands + caux ); + } + +#endif // REGISTER_VERBOSE_AUX_COMMANDS + +#ifdef REGISTER_VERBOSE_AUX_DATA + + // register aux data + for ( unsigned int cauxd = 0; cauxd < NUM_VERBOSE_AUX_DATA; cauxd++ ) { + + //NOTE: + // bit 7 of the persistence field is used to denote + // special aux data that may be excluded from registration. + + #ifdef EXCLUDE_SPECIAL_AUX_DATA + + if ( verbose_aux_data[ cauxd ].persistence & 0x80 ) + continue; + + #endif + + // destructive but doesn't matter here + verbose_aux_data[ cauxd ].persistence &= ~0x80; + + CON_RegisterIntCommand( verbose_aux_data + cauxd ); + } + +#endif // REGISTER_VERBOSE_AUX_DATA + +} + + + diff --git a/src/parsec/con_cani.cpp b/src/parsec/con_cani.cpp new file mode 100644 index 0000000..4e66fca --- /dev/null +++ b/src/parsec/con_cani.cpp @@ -0,0 +1,627 @@ +/* + * PARSEC - Color Animation Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1999 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// mathematics header +#include "utl_math.h" + +// local module header +#include "con_cani.h" + +// proprietary module headers +#include "con_arg.h" +#include "con_aux.h" +#include "con_main.h" +#include "e_colani.h" + + + +// string constants ----------------------------------------------------------- +// +static char colanim_name_missing[] = "name of colanim must be specified."; +static char colanim_name_invalid[] = "name invalid."; +static char colanim_mode_invalid[] = "mode invalid."; +static char colanim_len0_invalid[] = "len invalid."; +static char colanim_len1_invalid[] = "len2 invalid."; +static char colanim_len1_missing[] = "len2 missing but src2 specified."; +static char colanim_tab1_missing[] = "src2 missing but len2 specified."; +static char colanim_comp0_invalid[] = "comp is invalid (src)."; +static char colanim_comp1_invalid[] = "comp is invalid (src2)."; +static char colanim_t0_invalid[] = "tequi is invalid (src)."; +static char colanim_t1_invalid[] = "tequi is invalid (src2)."; +static char colanim_tl0_invalid[] = "tlist is invalid (src)."; +static char colanim_tl1_invalid[] = "tlist is invalid (src2)."; +static char colanim_w0_invalid[] = "invalid wave spec (src)."; +static char colanim_w1_invalid[] = "invalid wave spec (src2)."; +static char colanim_min0_invalid[] = "invalid min value (src)."; +static char colanim_min1_invalid[] = "invalid min value (src2)."; +static char colanim_max0_invalid[] = "invalid max value (src)."; +static char colanim_max1_invalid[] = "invalid max value (src2)."; +static char colanim_mask0_invalid[] = "invalid channel mask (src)."; +static char colanim_mask1_invalid[] = "invalid channel mask (src2)."; +static char colanim_reg_failed[] = "colanim registration failed."; + + +// key tables for colanim registration via console command -------------------- +// +key_value_s colanim_key_value[] = { + + { "src", NULL, KEYVALFLAG_PARENTHESIZE | KEYVALFLAG_MANDATORY }, + { "len", NULL, KEYVALFLAG_NONE | KEYVALFLAG_MANDATORY }, + { "src2", NULL, KEYVALFLAG_PARENTHESIZE }, + { "len2", NULL, KEYVALFLAG_NONE }, + { "mode", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_COLANI_SRC0, + KEY_COLANI_LEN0, + KEY_COLANI_SRC1, + KEY_COLANI_LEN1, + KEY_COLANI_MODE +}; + + +key_value_s colanim_tab_key_value[] = { + + { "tab", NULL, KEYVALFLAG_PARENTHESIZE | KEYVALFLAG_MANDATORY }, + { "comp", NULL, KEYVALFLAG_NONE }, + { "t", NULL, KEYVALFLAG_NONE }, + { "tl", NULL, KEYVALFLAG_PARENTHESIZE }, + { "mask", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_COLANI_TAB_TAB, + KEY_COLANI_TAB_COMP, + KEY_COLANI_TAB_TEQUI, + KEY_COLANI_TAB_TLIST, + KEY_COLANI_TAB_MASK +}; + + +key_value_s colanim_wav_key_value[] = { + + { "wave", NULL, KEYVALFLAG_MANDATORY }, + { "t", NULL, KEYVALFLAG_NONE }, + { "max", NULL, KEYVALFLAG_NONE }, + { "min", NULL, KEYVALFLAG_NONE }, + { "mask", NULL, KEYVALFLAG_NONE }, + + { NULL, NULL, KEYVALFLAG_NONE }, +}; + +enum { + + KEY_COLANI_WAV_WAVE, + KEY_COLANI_WAV_TEQUI, + KEY_COLANI_WAV_MAX, + KEY_COLANI_WAV_MIN, + KEY_COLANI_WAV_MASK +}; + +static char colanim_wave_separator[] = "wave "; +static int colanim_wave_seplen = strlen( colanim_wave_separator ); + + +// waveform specs ------------------------------------------------------------- +// +static char colanim_wave_tri[] = "tri"; +static char colanim_wave_saw[] = "saw"; +static char colanim_wave_ramp[] = "ramp"; +static char colanim_wave_sine[] = "sine"; + + +// store color and timing info into colanim entry ----------------------------- +// +#define SET_COLTAB_ENTRY(p,v,t) { \ + coltab[ p ].color.R = ( mask & 0x01 ) ? (byte)(v) : 0x00; \ + coltab[ p ].color.G = ( mask & 0x02 ) ? (byte)(v) : 0x00; \ + coltab[ p ].color.B = ( mask & 0x04 ) ? (byte)(v) : 0x00; \ + coltab[ p ].color.A = ( mask & 0x08 ) ? (byte)(v) : 0x00; \ + coltab[ p ].deltatime = (t); \ +} + + +// check and parse color channel mask ----------------------------------------- +// +PRIVATE +int CheckChannelMask( char *maskstr, dword *mask ) +{ + ASSERT( mask != NULL ); + + if ( maskstr != NULL ) { + + *mask = 0x00; + + if ( maskstr[ 0 ] == 'r' ) { + *mask |= 0x01; + maskstr++; + } + if ( maskstr[ 0 ] == 'g' ) { + *mask |= 0x02; + maskstr++; + } + if ( maskstr[ 0 ] == 'b' ) { + *mask |= 0x04; + maskstr++; + } + if ( maskstr[ 0 ] == 'a' ) { + *mask |= 0x08; + maskstr++; + } + if ( ( maskstr[ 0 ] != ' ' ) && ( maskstr[ 0 ] != 0 ) ) { + return FALSE; + } + } + + return TRUE; +} + + +// check for waveform specs --------------------------------------------------- +// +PRIVATE +int CheckWaveSpec( char *tabstr, colfrm_s *coltab, size_t tabsize, int tid ) +{ + ASSERT( tabstr != NULL ); + ASSERT( coltab != NULL ); + ASSERT( ( tid == 0 ) || ( tid == 1 ) ); + + // scan out all values to colanim_wav keys + if ( !ScanKeyValuePairs( colanim_wav_key_value, tabstr ) ) { + return FALSE; + } + + // timing + int tequi = 200; + if ( colanim_wav_key_value[ KEY_COLANI_WAV_TEQUI ].value != NULL ) { + if ( ScanKeyValueInt( &colanim_wav_key_value[ KEY_COLANI_WAV_TEQUI ], &tequi ) < 0 ) { + CON_AddLine( tid ? colanim_t1_invalid : colanim_t0_invalid ); + return FALSE; + } + if ( tequi < 1 ) { + CON_AddLine( tid ? colanim_t1_invalid : colanim_t0_invalid ); + return FALSE; + } + } + + // lower bound + int minval = 0; + if ( colanim_wav_key_value[ KEY_COLANI_WAV_MIN ].value != NULL ) { + if ( ScanKeyValueInt( &colanim_wav_key_value[ KEY_COLANI_WAV_MIN ], &minval ) < 0 ) { + CON_AddLine( tid ? colanim_min1_invalid : colanim_min0_invalid ); + return FALSE; + } + if ( ( minval < 0 ) || ( minval > 255 ) ) { + CON_AddLine( tid ? colanim_min1_invalid : colanim_min0_invalid ); + return FALSE; + } + } + + // upper bound + int maxval = 255; + if ( colanim_wav_key_value[ KEY_COLANI_WAV_MAX ].value != NULL ) { + if ( ScanKeyValueInt( &colanim_wav_key_value[ KEY_COLANI_WAV_MAX ], &maxval ) < 0 ) { + CON_AddLine( tid ? colanim_max1_invalid : colanim_max0_invalid ); + return FALSE; + } + if ( ( maxval < minval ) || ( maxval > 255 ) ) { + CON_AddLine( tid ? colanim_max1_invalid : colanim_max0_invalid ); + return FALSE; + } + } + + // check for color channel mask + dword mask = 0x0f; + if ( !CheckChannelMask( colanim_wav_key_value[ KEY_COLANI_WAV_MASK ].value, &mask ) ) { + CON_AddLine( tid ? colanim_mask1_invalid : colanim_mask0_invalid ); + return FALSE; + } + + // generate specified waveform + char *wave = colanim_wav_key_value[ KEY_COLANI_WAV_WAVE ].value; + + if ( strcmp( wave, colanim_wave_tri ) == 0 ) { + + // triangle: "/\" + if ( tabsize < 2 ) { + SET_COLTAB_ENTRY( 0, minval, tequi ); + return TRUE; + } + unsigned int halft = tabsize / 2; + float step = (float)( maxval - minval ) / (float)halft; + float curval = (float)minval; + unsigned int tpos = 0; + for ( tpos = 0; tpos < halft; tpos++ ) { + SET_COLTAB_ENTRY( tpos, curval, tequi ); + curval += step; + } + for ( ; tpos < tabsize; tpos++ ) { + SET_COLTAB_ENTRY( tpos, curval, tequi ); + curval -= step; + } + + } else if ( strcmp( wave, colanim_wave_saw ) == 0 ) { + + // sawtooth: "|\" + if ( tabsize < 2 ) { + SET_COLTAB_ENTRY( 0, minval, tequi ); + return TRUE; + } + float step = (float)( maxval - minval ) / (float)( tabsize - 1 ); + float curval = (float)maxval; + for ( unsigned int tpos = 0; tpos < tabsize; tpos++ ) { + SET_COLTAB_ENTRY( tpos, curval, tequi ); + curval -= step; + } + + } else if ( strcmp( wave, colanim_wave_ramp ) == 0 ) { + + // ramp: "/|" + if ( tabsize < 2 ) { + SET_COLTAB_ENTRY( 0, minval, tequi ); + return TRUE; + } + float step = (float)( maxval - minval ) / (float)( tabsize - 1 ); + float curval = (float)minval; + for ( unsigned int tpos = 0; tpos < tabsize; tpos++ ) { + SET_COLTAB_ENTRY( tpos, curval, tequi ); + curval += step; + } + + } else if ( strcmp( wave, colanim_wave_sine ) == 0 ) { + + // sine + float step = (float)BAMS_DEG360 / (float)tabsize; + float base = (float)( maxval + minval ) / 2; + float ampl = (float)( maxval - minval ) / 2; + float curval = (float)BAMS_DEG0; + for ( unsigned int tpos = 0; tpos < tabsize; tpos++ ) { + sincosval_s sincos; + GetSinCos( (dword)curval, &sincos ); + float cursig = ampl * GEOMV_TO_FLOAT( sincos.sinval ); + SET_COLTAB_ENTRY( tpos, base + cursig, tequi ); + curval += step; + } + + } else { + + CON_AddLine( tid ? colanim_w1_invalid : colanim_w0_invalid ); + return FALSE; + } + + return TRUE; +} + + +// parse entire color table of 1, 3, or 4 components -------------------------- +// +PRIVATE +int ParseColorTable( char *tabstr, colfrm_s *coltab, int *intlist, size_t tabsize, int tid ) +{ + ASSERT( tabstr != NULL ); + ASSERT( coltab != NULL ); + ASSERT( intlist != NULL ); + ASSERT( ( tid == 0 ) || ( tid == 1 ) ); + + // check for wave spec instead of table + while ( *tabstr == ' ' ) + tabstr++; + if ( strncmp( tabstr, colanim_wave_separator, colanim_wave_seplen ) == 0 ) { + return CheckWaveSpec( tabstr, coltab, tabsize, tid ); + } + + // scan out all values to colanim_tab keys + if ( !ScanKeyValuePairs( colanim_tab_key_value, tabstr ) ) { + return FALSE; + } + + // number of color components + int comp = 1; + if ( ScanKeyValueInt( &colanim_tab_key_value[ KEY_COLANI_TAB_COMP ], &comp ) < 0 ) { + CON_AddLine( tid ? colanim_comp1_invalid : colanim_comp0_invalid ); + return FALSE; + } + if ( ( comp != 1 ) && ( comp != 3 ) && ( comp != 4 ) ) { + CON_AddLine( tid ? colanim_comp1_invalid : colanim_comp0_invalid ); + return FALSE; + } + + // check for color channel mask + dword mask = 0x0f; + if ( !CheckChannelMask( colanim_tab_key_value[ KEY_COLANI_TAB_MASK ].value, &mask ) ) { + CON_AddLine( tid ? colanim_mask1_invalid : colanim_mask0_invalid ); + return FALSE; + } + + // timing + int tequi = 200; + int tlist = FALSE; + if ( colanim_tab_key_value[ KEY_COLANI_TAB_TEQUI ].value != NULL ) { + + if ( ScanKeyValueInt( &colanim_tab_key_value[ KEY_COLANI_TAB_TEQUI ], &tequi ) < 0 ) { + CON_AddLine( tid ? colanim_t1_invalid : colanim_t0_invalid ); + return FALSE; + } + if ( tequi < 1 ) { + CON_AddLine( tid ? colanim_t1_invalid : colanim_t0_invalid ); + return FALSE; + } + + } else if ( colanim_tab_key_value[ KEY_COLANI_TAB_TLIST ].value != NULL ) { + + if ( ScanKeyValueIntList( &colanim_tab_key_value[ KEY_COLANI_TAB_TLIST ], + intlist, tabsize, tabsize ) == 0 ) { + CON_AddLine( tid ? colanim_tl1_invalid : colanim_tl0_invalid ); + return FALSE; + } + tlist = TRUE; + } + if ( tlist ) { + for ( unsigned int eid = 0; eid < tabsize; eid++ ) { + if ( intlist[ eid ] < 1 ) { + CON_AddLine( tid ? colanim_t1_invalid : colanim_t0_invalid ); + return FALSE; + } + coltab[ eid ].deltatime = intlist[ eid ]; + } + } else { + for ( unsigned int eid = 0; eid < tabsize; eid++ ) { + coltab[ eid ].deltatime = tequi; + } + } + + // color components + size_t complistlen = comp * tabsize; + if ( ScanKeyValueIntList( &colanim_tab_key_value[ KEY_COLANI_TAB_TAB ], + intlist, complistlen, complistlen ) == 0 ) { + CON_AddLine( tid ? colanim_tl1_invalid : colanim_tl0_invalid ); + return FALSE; + } + int *complist = intlist; + for ( unsigned int eid = 0; eid < tabsize; eid++, complist += comp ) { + + switch ( comp ) { + + case 1: + coltab[ eid ].color.R = ( mask & 0x01 ) ? complist[ 0 ] : 0x00; + coltab[ eid ].color.G = ( mask & 0x02 ) ? complist[ 0 ] : 0x00; + coltab[ eid ].color.B = ( mask & 0x04 ) ? complist[ 0 ] : 0x00; + coltab[ eid ].color.A = ( mask & 0x08 ) ? complist[ 0 ] : 0x00; + break; + + case 3: + coltab[ eid ].color.R = ( mask & 0x01 ) ? complist[ 0 ] : 0x00; + coltab[ eid ].color.G = ( mask & 0x02 ) ? complist[ 1 ] : 0x00; + coltab[ eid ].color.B = ( mask & 0x04 ) ? complist[ 2 ] : 0x00; + coltab[ eid ].color.A = ( mask & 0x08 ) ? 0xff : 0x00; + break; + + case 4: + coltab[ eid ].color.R = ( mask & 0x01 ) ? complist[ 0 ] : 0x00; + coltab[ eid ].color.G = ( mask & 0x02 ) ? complist[ 1 ] : 0x00; + coltab[ eid ].color.B = ( mask & 0x04 ) ? complist[ 2 ] : 0x00; + coltab[ eid ].color.A = ( mask & 0x08 ) ? complist[ 3 ] : 0x00; + break; + } + } + + return TRUE; +} + + +// possible colanim_s::col_flags modes (COLANIM_SOURCExx) --------------------- +// +static char colanim_mode_sourcenocomb[] = "nocombine"; +static char colanim_mode_sourceadd[] = "add"; +static char colanim_mode_sourcemul[] = "mul"; + + +// console command for registering new colanim ("colanim") -------------------- +// +int Cmd_DefColAnim( char *command ) +{ + //NOTE: + //CONCOM: + // colanim_command ::= 'colanim' [] [] + // name ::= "may be parenthesized to include whitespace" + // coltab0 ::= 'src' 'len' + // coltab1 ::= 'src2' 'len2' + // coltab_src ::= '(' | ')' + // coltab_len ::= + // mode_spec ::= 'mode' 'add' | 'mul' + // tab_spec ::= 'tab' [] [] [ | ] + // col_list ::= '(' + ')' + // comp ::= 'comp' '1' | '3' | '4' + // t_equi ::= 't' + // t_list ::= 'tl' '(' + ')' + // wave_spec ::= 'wave' [] [] [] [] + // wave_name ::= 'tri' | 'saw' | 'ramp' | 'sine' + // max ::= 'max' + // min ::= 'min' + // mask ::= 'mask' ['r'] ['g'] ['b'] ['a'] + + ASSERT( command != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( command ); + + // this flag is used during internal data reloads + if ( AUX_ALLOW_ONLY_TEXTURE_LOADING ) { + return TRUE; + } + + // create pointer to list of parameters (first is always the name) + char *colanimname = strtok( command, " " ); + if ( colanimname == NULL ) { + CON_AddLine( colanim_name_missing ); + return TRUE; + } + + // allow name to be parenthesized to include whitespace + colanimname = GetParenthesizedName( colanimname ); + if ( colanimname == NULL ) { + CON_AddLine( colanim_name_invalid ); + return TRUE; + } + + // scan out all values to colanim keys + if ( !ScanKeyValuePairs( colanim_key_value, NULL ) ) + return TRUE; + + // fetch length of coltab0 + int len0; + if ( ScanKeyValueInt( &colanim_key_value[ KEY_COLANI_LEN0 ], &len0 ) < 0 ) { + CON_AddLine( colanim_len0_invalid ); + return TRUE; + } + if ( ( len0 < 1 ) || ( len0 > 256 ) ) { + CON_AddLine( colanim_len0_invalid ); + return TRUE; + } + + // fetch length of coltab1 + int len1 = 0; + if ( colanim_key_value[ KEY_COLANI_LEN1 ].value != NULL ) { + if ( ScanKeyValueInt( &colanim_key_value[ KEY_COLANI_LEN1 ], &len1 ) < 0 ) { + CON_AddLine( colanim_len1_invalid ); + return TRUE; + } + if ( ( len1 < 1 ) || ( len1 > 256 ) ) { + CON_AddLine( colanim_len1_invalid ); + return TRUE; + } + } + + // check whether both len1 and coltab1 specified or none at all + if ( colanim_key_value[ KEY_COLANI_SRC1 ].value != NULL ) { + if ( len1 < 1 ) { + CON_AddLine( colanim_len1_missing ); + return TRUE; + } + } else { + if ( len1 > 0 ) { + CON_AddLine( colanim_tab1_missing ); + return TRUE; + } + } + + // parse mode if supplied + dword mode = COLANIM_SOURCEADD; + if ( colanim_key_value[ KEY_COLANI_MODE ].value != NULL ) { + char *modestr = colanim_key_value[ KEY_COLANI_MODE ].value; + if ( strcmp( modestr, colanim_mode_sourceadd ) == 0 ) { + mode = COLANIM_SOURCEADD; + } else if ( strcmp( modestr, colanim_mode_sourcemul ) == 0 ) { + mode = COLANIM_SOURCEMUL; + } else if ( strcmp( modestr, colanim_mode_sourcenocomb ) == 0 ) { + mode = COLANIM_SOURCENOCOMBINE; + } else { + CON_AddLine( colanim_mode_invalid ); + return TRUE; + } + } + + // reserve table memory (both tables in one block) + size_t tabsize = ( len0 + len1 ); + char *tabmem = (char *) ALLOCMEM( tabsize * sizeof( colfrm_s ) ); + if ( tabmem == NULL ) + OUTOFMEM( 0 ); + colfrm_s *coltab0 = (colfrm_s *) tabmem; + colfrm_s *coltab1 = ( len1 > 0 ) ? &coltab0[ len0 ] : NULL; + + // need tempmem for color lists (maximum four components per color) + size_t tempsize = max( len0, len1 ) * 4; + char *tempmem = (char *) ALLOCMEM( tempsize * sizeof( int ) ); + if ( tempmem == NULL ) + OUTOFMEM( 0 ); + int *intlist = (int *) tempmem; + + // parse coltab0 + char *coltab0str = colanim_key_value[ KEY_COLANI_SRC0 ].value; + if ( !ParseColorTable( coltab0str, coltab0, intlist, len0, 0 ) ) { + FREEMEM( tempmem ); + FREEMEM( tabmem ); + return TRUE; + } + + // parse coltab1 if supplied + char *coltab1str = colanim_key_value[ KEY_COLANI_SRC1 ].value; + if ( coltab1str != NULL ) { + if ( !ParseColorTable( coltab1str, coltab1, intlist, len1, 1 ) ) { + FREEMEM( tempmem ); + FREEMEM( tabmem ); + return TRUE; + } + } + + // init registration info + colanim_s colanim; + colanim.col_table0 = coltab0; + colanim.col_table1 = coltab1; + colanim.col_end0 = ( len0 - 1 ); + colanim.col_end1 = ( len1 > 0 ) ? ( len1 - 1 ) : 0; + colanim.col_flags = mode; + + colanimreg_s colanimreg; + colanimreg.name = colanimname; + colanimreg.colanim = colanim; + + // do registration + if ( !RegisterColAnim( &colanimreg ) ) { + + CON_AddLine( colanim_reg_failed ); + FREEMEM( tempmem ); + FREEMEM( tabmem ); + return TRUE; + } + + // free temporary mem + FREEMEM( tempmem ); + + return TRUE; +} + + + diff --git a/src/parsec/con_com.cpp b/src/parsec/con_com.cpp new file mode 100644 index 0000000..af671e7 --- /dev/null +++ b/src/parsec/con_com.cpp @@ -0,0 +1,1156 @@ +/* + * PARSEC - Common Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1996-1999 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" +#include "od_props.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" +#include "inp_defs.h" +#include "net_defs.h" +#include "vid_defs.h" + +// local module header +#include "con_com.h" + +// proprietary module headers +#include "con_act.h" +#include "con_arg.h" +#include "con_aux.h" +#include "con_cani.h" +#include "con_conf.h" +#include "con_ext.h" +#include "con_info.h" +#include "con_int.h" +#include "con_list.h" +#include "con_load.h" +#include "con_main.h" +#include "con_say.h" +#include "con_shad.h" +#include "con_std.h" +#include "e_demo.h" +#include "e_supp.h" +#include "g_supp.h" +#include "h_supp.h" +#include "m_main.h" +#include "net_conn.h" +#include "obj_ctrl.h" +#include "sys_date.h" +#include "sys_path.h" +#include "vid_init.h" +#include "vid_plug.h" + + + +// generic string paste area -------------------------------------------------- +// +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// string constants ----------------------------------------------------------- +// +static char base_str[] = "base is set to dec."; +#define BASE_INSERT_POS 15 +static char base_dec[] = "dec."; +static char base_hex[] = "hex."; +static char base_oct[] = "oct."; +static char base_set_to_dec[] = "base set to dec."; +static char base_set_to_hex[] = "base set to hex."; +static char base_set_to_oct[] = "base set to oct."; +static char info_sep_line[] = "-----------------------------------------------"; +PUBLIC char dont_use_params[] = "this command takes no parameters."; +static char server_name_missing[] = "server must be supplied."; +static char mode_number_invalid[] = "invalid mode number."; +static char mode_spec_invalid[] = "invalid mode specifier. use something like \"640x480x32\"."; +static char mode_spec_unavail[] = "this mode is not available in the current video subsystem."; +static char mode_modifier_invalid[] = "invalid mode modifier. use \"fullscreen\" or \"windowed\"."; +static char only_alpha_chars[] = "name must not contain non-alphabetic characters."; +static char name_change_preempted[] = "name change preempted. please try again."; + + +// remove all objects (command "objectclear") --------------------------------- +// +PRIVATE +void Cmd_OBJECTCLEAR() +{ + // free objects and particles + KillAllObjects(); +} + + +// print object counts for all object lists (command "objectcount") ----------- +// +PRIVATE +void Cmd_OBJECTCOUNT() +{ + GenObject *walklist; + int listlength; + + listlength = 0; + for ( walklist = FetchFirstShip(); walklist; walklist = walklist->NextObj ) + listlength++; + sprintf( paste_str, "ships :%3d", listlength ); + CON_AddLine( paste_str ); + + listlength = 0; + for ( walklist = FetchFirstLaser(); walklist; walklist = walklist->NextObj ) + listlength++; + sprintf( paste_str, "lasers :%3d", listlength ); + CON_AddLine( paste_str ); + + listlength = 0; + for ( walklist = FetchFirstMissile(); walklist; walklist = walklist->NextObj ) + listlength++; + sprintf( paste_str, "missiles:%3d", listlength ); + CON_AddLine( paste_str ); + + listlength = 0; + for ( walklist = FetchFirstExtra(); walklist; walklist = walklist->NextObj ) + listlength++; + sprintf( paste_str, "extras :%3d (obj, counted %d) and %d particle", + listlength, CurrentNumExtras, CurrentNumPrtExtras ); + CON_AddLine( paste_str ); + + listlength = 0; + for ( walklist = FetchFirstCustom(); walklist; walklist = walklist->NextObj ) + listlength++; + sprintf( paste_str, "customs :%3d", listlength ); + CON_AddLine( paste_str ); +} + + +// display heap info (command "heap") ----------------------------------------- +// +#ifdef PARSEC_DEBUG +PRIVATE +int Cmd_HEAP( char *params ) +{ + ASSERT( params != NULL ); + USERCOMMAND_NOPARAM( params ); + + extern unsigned int Dyn_Mem_Size; + extern unsigned int Num_Allocs; + extern unsigned int Num_Frees; + + sprintf( paste_str, "heapsize: %.2fmb :%d", (float) Dyn_Mem_Size / ( 1024 * 1024 ), Dyn_Mem_Size ); + CON_AddLine( paste_str ); + sprintf( paste_str, "memobjs : %d", Num_Allocs - Num_Frees ); + CON_AddLine( paste_str ); + + return TRUE; +} +#endif // PARSEC_DEBUG + + +// show position of local ship (command "showposition") ----------------------- +// +PRIVATE +void Cmd_SHOWPOSITION() +{ + sprintf( paste_str, "x position: %13f", GEOMV_TO_FLOAT( MyShip->ObjPosition[ 0 ][ 3 ] ) ); + CON_AddLine( paste_str ); + + sprintf( paste_str, "y position: %13f", GEOMV_TO_FLOAT( MyShip->ObjPosition[ 1 ][ 3 ] ) ); + CON_AddLine( paste_str ); + + sprintf( paste_str, "z position: %13f", GEOMV_TO_FLOAT( MyShip->ObjPosition[ 2 ][ 3 ] ) ); + CON_AddLine( paste_str ); +} + + +// player name has been changed -> change remote name accordingly ------------- +// +void CheckPlayerName( const char *name ) +{ + ASSERT( name != NULL ); + +/* + for ( char *scan = name; *scan; scan++ ) { + + // allow only alphabetic chars + if ( !isalpha( *scan ) ) { + CON_AddLine( only_alpha_chars ); + return; + } + + // convert to lowercase + *scan = tolower( *scan ); + } +*/ + // exit if name not altered + if ( strcmp( LocalPlayerName, name ) == 0 ) { + + //NOTE: + // this happens either if the user tried to set + // the same name again, or supplied no argument + // and therefore only queried the current name. + + return; + } + + // ensure everybody knows about new name + if ( NET_SetPlayerName( name ) ) { + sprintf( paste_str, "name set to %s.", LocalPlayerName ); + CON_AddLine( paste_str ); + } else { + CON_AddLine( name_change_preempted ); + } +} + + +// open output script for writing (don't overwrite existing file) ------------- +// +PRIVATE +int Cmd_Create( char *command ) +{ + return OpenOutputBatch( command, CM_CREATE ); +} + + +// open output script for writing (overwrite existing file) ------------------- +// +PRIVATE +int Cmd_Open( char *command ) +{ + return OpenOutputBatch( command, CM_OPEN ); +} + + +// append to output script ---------------------------------------------------- +// +PRIVATE +int Cmd_Append( char *command ) +{ + return OpenOutputBatch( command, CM_APPEND ); +} + + +// record demo script after saving state -------------------------------------- +// +PRIVATE +int Cmd_Recdem( char *command ) +{ + return StartRecording( command, TRUE ); +} + + +// record demo script without saving state first ------------------------------ +// +PRIVATE +int Cmd_Record( char *command ) +{ + return StartRecording( command, FALSE ); +} + + +// print parsec build info (command "build") ---------------------------------- +// +PRIVATE +int Cmd_BuildInfo( char *cstr ) +{ + ASSERT( cstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( cstr ); + + // split off first token (detail) + char *dstr = strtok( cstr, " " ); + if ( dstr == NULL ) { + // display basic build info + CON_AddLine( build_text ); + CON_AddLine( build_date ); + CON_AddLine( build_time ); + return TRUE; + } + + // check if more than one parameter + if ( strtok( NULL, " " ) != NULL ) { + CON_AddLine( too_many_args ); + return TRUE; + } + + // check for detail spec + if ( strcmp( dstr, "x" ) == 0 ) { + + CON_AddLine( info_sep_line ); + CON_AddLine( build_text ); + CON_AddLine( info_sep_line ); + CON_AddLine( build_date ); + CON_AddLine( build_time ); + CON_AddLine( info_sep_line ); + DisplayCurrentNetSubsys(); + CON_AddLine( info_sep_line ); + CON_AddLine( build_comp ); + CON_AddLine( build_bind ); + CON_AddLine( build_endn ); + CON_AddLine( info_sep_line ); + + } else { + + CON_AddLine( invalid_arg ); + } + + return TRUE; +} + + +// exec display command (display arbitrary text in message area) -------------- +// +PRIVATE +int Cmd_DisplayText( char *cstr ) +{ + ASSERT( cstr != NULL ); + HANDLE_COMMAND_DOMAIN( cstr ); + + const char *scan = GetStringBehindCommand( cstr, FALSE ); + + if ( ( scan != NULL ) && ( strlen( scan ) <= MAX_MESSAGELEN ) ) { + ShowMessage( scan ); + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// exec write command (display arbitrary text in console) --------------------- +// +PRIVATE +int Cmd_WriteText( char *cstr ) +{ + //NOTE: + // this command normally only makes sense if + // used from within a console script. + + ASSERT( cstr != NULL ); + HANDLE_COMMAND_DOMAIN( cstr ); + + const char *scan = GetStringBehindCommand( cstr, TRUE ); + + // output string in console (new-line possible) + if ( scan != NULL ) { + if ( TextModeActive && AUX_CMD_WRITE_ACTIVE_IN_TEXTMODE ) + MSGPUT( "\n::%s", scan ); + if ( !AUX_CMD_WRITE_DISABLE_OUTPUT ) + CON_AddLine( scan ); + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// set current working directory (general use) -------------------------------- +// +PRIVATE +int Cmd_SetPathWorkingDirectory( char *command ) +{ + ASSERT( command != NULL ); + HANDLE_COMMAND_DOMAIN( command ); + + if ( SetSingleStringCommand( command, CurWorkDir, PATH_MAX ) ) { + + // process file name + char *path = SYSs_ProcessPathString( CurWorkDir ); + if ( path != CurWorkDir ) { + strncpy( CurWorkDir, path, PATH_MAX ); + CurWorkDir[ PATH_MAX ] = 0; + } + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// set file path for intro animation ------------------------------------------ +// +PRIVATE +int Cmd_SetPathAnimIntro( char *command ) +{ + ASSERT( command != NULL ); + HANDLE_COMMAND_DOMAIN( command ); + + /* + extern char demo_movie_name[]; + if ( SetSingleStringCommand( command, demo_movie_name, PATH_MAX ) ) { + + // process file name and use current workdir + strcpy( demo_movie_name, SubstCurWorkDir( demo_movie_name ) ); + } + */ + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// set file path for all audio streams ---------------------------------------- +// +PRIVATE +int Cmd_SetPathAudioStreams( char *command ) +{ + ASSERT( command != NULL ); + HANDLE_COMMAND_DOMAIN( command ); + + if ( SetSingleStringCommand( command, console_audio_stream_path, PATH_MAX ) ) { + + // process file name and use current workdir + strcpy( console_audio_stream_path, SubstCurWorkDir( console_audio_stream_path ) ); + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// set file path for intro audio stream --------------------------------------- +// +PRIVATE +int Cmd_SetPathAudioStreamIntro( char *command ) +{ + ASSERT( command != NULL ); + HANDLE_COMMAND_DOMAIN( command ); + + if ( SetSingleStringCommand( command, intro_stream_name, PATH_MAX ) ) { + + // process file name and use current workdir + strcpy( intro_stream_name, SubstCurWorkDir( intro_stream_name ) ); + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// set file path for menu audio stream ---------------------------------------- +// +PRIVATE +int Cmd_SetPathAudioStreamMenu( char *command ) +{ + ASSERT( command != NULL ); + HANDLE_COMMAND_DOMAIN( command ); + + if ( SetSingleStringCommand( command, menu_stream_name, PATH_MAX ) ) { + + // process file name and use current workdir + strcpy( menu_stream_name, SubstCurWorkDir( menu_stream_name ) ); + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// flash screen white --------------------------------------------------------- +// +PRIVATE +void Cmd_FLASHWHITE() +{ + SetScreenWhite = LASER2_INTENSITY * 16; +} + + +// flash screen blue ---------------------------------------------------------- +// +PRIVATE +void Cmd_FLASHBLUE() +{ + SetScreenBlue = FLASHTIME_LASER_THIEF; +} + + +// init console talk mode ----------------------------------------------------- +// +PRIVATE +void InitTalkMode() +{ + ASSERT( con_in_talk_mode ); + + // clear screen, set cursor to screen-bottom line + ClearConScreen(); + + // create separator line + CreateSeparatorLine( con_bottom ); + + // save number of line right below separator line + CON_AddLineFeed(); + CON_DisableLineFeed(); + con_talk_line = con_bottom; +} + + +// command "cls" -------------------------------------------------------------- +// +PRIVATE +void Cmd_CLS() +{ + if ( con_in_talk_mode ) { + + // reactivate talkmode + InitTalkMode(); + + } else { + + // ensure automatic linefeed will not be eaten + CON_EnableLineFeed(); + + // ensure that after successive linefeed + // ( con_bottom == 0 ) && ( con_content == 1 ) + con_bottom = -1; + con_content = 0; + + // reset back-viewing + con_back_view = 0; + } +} + + +// command "talk" (toggle talk mode on and off) ------------------------------- +// +PRIVATE +void Cmd_TALK() +{ + // toggle talk mode + con_in_talk_mode = !con_in_talk_mode; + + if ( con_in_talk_mode ) { + // talkmode init clears screen + InitTalkMode(); + } else { + // clear screen + Cmd_CLS(); + } +} + + +// command "hide" ------------------------------------------------------------- +// +PRIVATE +void Cmd_HIDE() +{ + //NOTE: + // simulate depression of the console + // toggle key. + + DepressedKeys->key_ToggleConsole = 1; +} + + +// command "quit" ------------------------------------------------------------- +// +PRIVATE +void Cmd_QUIT() +{ + //NOTE: + // simulate depression of the key. + // (or whatever is currently mapped to + // gamefunction escape) + + DepressedKeys->key_Escape = 1; +} + + +// command "exitgame" ------------------------------------------------------------- +// +PRIVATE +void Cmd_EXITGAME() +{ + ExitGameLoop = 3; +} + + +// command "enable" ----------------------------------------------------------- +// +PRIVATE +void Cmd_ENABLE() +{ + //NOTE: + // enable typing in console. keyboard input + // will be routed to the console instead of to + // the game. the console cursor will be blinking + // to signify this. + + KeybFlags->ConActive = 0xff; +} + + +// command "disable" ---------------------------------------------------------- +// +PRIVATE +void Cmd_DISABLE() +{ + //NOTE: + // disable typing in console. keyboard input + // will be routed to the game instead of to + // the console, even if the console is enabled. + // the console cursor will not be blinking + // to signify this. + + KeybFlags->ConActive = 0x00; +} + + +// command "hex" -------------------------------------------------------------- +// +PRIVATE +void Cmd_HEX() +{ + int_print_base = "%x"; + int_calc_base = 16; + CON_AddLine( base_set_to_hex ); + strcpy( base_str + BASE_INSERT_POS, base_hex ); +} + + +// command "dec" -------------------------------------------------------------- +// +PRIVATE +void Cmd_DEC() +{ + int_print_base = "%d"; + int_calc_base = 10; + CON_AddLine( base_set_to_dec ); + strcpy( base_str + BASE_INSERT_POS, base_dec ); +} + + +// command "oct" -------------------------------------------------------------- +// +PRIVATE +void Cmd_OCT() +{ + int_print_base = "%o"; + int_calc_base = 8; + CON_AddLine( base_set_to_oct ); + strcpy( base_str + BASE_INSERT_POS, base_oct ); +} + + +// command "base" ------------------------------------------------------------- +// +PRIVATE +void Cmd_BASE() +{ + CON_AddLine( base_str ); +} + + +// set video mode to specified mode number ------------------------------------ +// +PRIVATE +int Cmd_SetVidMode( char *modestr ) +{ + ASSERT( modestr != NULL ); + HANDLE_COMMAND_DOMAIN( modestr ); + + // determine whether specifier should be parsed instead of mode number + // (specifiers like "640x480x32" and all valid modifiers contain at + // least one char not allowed in a hexadecimal mode number) + int parsespec = FALSE; + char *scan = NULL; + for ( scan = modestr; *scan != 0; scan++ ) { + if ( *scan == ' ' ) + continue; + if ( ( *scan >= '0' ) && ( *scan <= '9' ) ) + continue; + if ( ( *scan >= 'a' ) && ( *scan <= 'f' ) ) + continue; + if ( ( *scan >= 'A' ) && ( *scan <= 'F' ) ) + continue; + parsespec = TRUE; + break; + } + + int xres = 0, yres = 0; + bool fullscreen = false; + int bpp = 32; + + if ( parsespec ) { + + // read mode specifier + char *modespec = (char *) GetStringBehindCommand( modestr, FALSE ); + if ( modespec != NULL ) { + + // a modifier for explicit fullscreen/windowed modes may + // be appended to the specifier after a delimiting space + char *modifier = (char *) modespec; + while ( ( *modifier != ' ' ) && ( *modifier != 0 ) ) + modifier++; + + // if a mode is already active it is possible to just use a + // modifier to switch between windowed and fullscreen mode + int modifieronly = FALSE; + if ( !TextModeActive ) { + for ( scan = modespec; scan < modifier; scan++ ) { + if ( *scan == 'x' ) + break; + } + if ( scan == modifier ) { + modifieronly = TRUE; + modifier = modespec; + } + } + + // parse the (optional) modifier + int indxmodifier = -1; + if ( *modifier != 0 ) { + + if ( !modifieronly ) { + // sever spec and modifier + *modifier++ = 0; + // strip intermediate spaces + while ( *modifier == ' ' ) + modifier++; + } + + // modifier may be "fullscreen" or "windowed" + if ( strcmp( modifier, "fullscreen" ) == 0 ) { + indxmodifier = 1; + } else if ( strcmp( modifier, "windowed" ) == 0 ) { + indxmodifier = 0; + } else { + CON_AddLine( mode_modifier_invalid ); + return TRUE; + } + } + + if (modifieronly) { + xres = GameScreenRes.width; + yres = GameScreenRes.height; + bpp = GameScreenBPP; + } else { + int modearray[] = {0, 0, 0}; + + VID_MapSpecifierToMode(modespec, modearray); + + xres = modearray[0]; + yres = modearray[1]; + bpp = modearray[2]; + } + + if ( indxmodifier != -1 ) { + fullscreen = indxmodifier == 1 ? true : false; + } else { + fullscreen = !Op_WindowedMode ? true : false; + } + } + + } else { + + MSGOUT("Setting video mode using hex number no longer works!\n"); + } + + // switch to desired mode if mode number found. this doesn't mean that + // the mode is actually valid for the current video subsystem, if it + // was specified directly. (specifiers have been checked already.) + if ( xres != 0 && yres != 0 && bpp != 0 ) { + if ( !VID_HotChangeMode(xres, yres, fullscreen, bpp)) { + CON_AddLine( mode_number_invalid ); + } + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// connect to server ("connect") ---------------------------------------------- +// +PRIVATE +int Cmd_Connect( char *server ) +{ + ASSERT( server != NULL ); + HANDLE_COMMAND_DOMAIN( server ); + + // eat whitespace behind command + const char *scan = GetStringBehindCommand( server, FALSE ); + + if ( scan != NULL ) { + if ( NET_CommandConnect( scan ) ) { + MenuNotifyConnect(); + } + } else { + CON_AddLine( server_name_missing ); + } + + // recognize always (implicitly reserves domain) + return TRUE; +} + + +// close network connection ("disconnect") ------------------------------------ +// +PRIVATE +void Cmd_DISCONNECT() +{ + if ( NET_CommandDisconnect() ) { + MenuNotifyDisconnect(); + } +} + + +// commands corresponding to functions with no parameters --------------------- +// +struct cmd_noparam_s { + + int commandid; + void (*commandfunc)(void); +}; + +cmd_noparam_s cmd_noparam[] = { + + { CM_REPINFO, Cmd_QueryReplayInfo }, + { CM_REPSTOP, Cmd_StopBatchReplay }, + { CM_CLS, Cmd_CLS }, + { CM_CLEAR, Cmd_CLS }, + { CM_HIDE, Cmd_HIDE }, + { CM_QUIT, Cmd_QUIT }, + { CM_EXIT, Cmd_QUIT }, + { CM_EXITGAME, Cmd_EXITGAME }, + { CM_ENABLE, Cmd_ENABLE }, + { CM_DISABLE, Cmd_DISABLE }, + { CM_HEX, Cmd_HEX }, + { CM_DEC, Cmd_DEC }, + { CM_OCT, Cmd_OCT }, + { CM_BASE, Cmd_BASE }, + { CM_FLASHWHITE, Cmd_FLASHWHITE }, + { CM_FLASHBLUE, Cmd_FLASHBLUE }, + { CM_OBJECTCLEAR, Cmd_OBJECTCLEAR }, + { CM_OBJECTCOUNT, Cmd_OBJECTCOUNT }, + { CM_SHIPS, Cmd_ShipInfo }, + { CM_LISTCLASSES, Cmd_ListClasses }, + { CM_LISTTYPES, Cmd_ListTypes }, + { CM_LISTTEXTMACS, Cmd_ListSayMacros }, + { CM_LISTBINDINGS, Cmd_ListKeyBindings }, + { CM_SETORIGIN, Cmd_SetShipOrigin }, + { CM_SHOWPOSITION, Cmd_SHOWPOSITION }, + { CM_CLOSE, Cmd_CloseOutputBatch }, + { CM_LISTGAMEFUNCKEYS, Cmd_ListKeyFunctions }, + { CM_VID_LISTMODES, Cmd_ListVidModes }, + { CM_DISCONNECT, Cmd_DISCONNECT }, + { CM_TALKMODE, Cmd_TALK }, + { CM_RESCAN, Cmd_RescanExternalCommands }, + { CM_LISTDEMOS, Cmd_ListBinaryDemos }, +}; + +#define NUM_CMDS_NOPARAM CALC_NUM_ARRAY_ENTRIES( cmd_noparam ) + + +// commands corresponding to functions with no parameters --------------------- +// +int CheckCmdsNoParam( const char *command ) +{ + //NOTE: + // this function returns TRUE if a valid command + // has been detected and executed. it returns + // FALSE if no valid command has been detected + // and the command string therefore needs + // further processing by the main dispatcher. + + ASSERT( command != NULL ); + + // check for commands in "no param" table + for ( unsigned int tid = 0; tid < NUM_CMDS_NOPARAM; tid++ ) { + + const char *cmdstr = CMSTR( cmd_noparam[ tid ].commandid ); + int cmdlen = CMLEN( cmd_noparam[ tid ].commandid ); + + if ( strncmp( command, cmdstr, cmdlen ) == 0 ) { + + // eat trailing whitespace + const char *whsp = command + cmdlen; + for ( ; *whsp; whsp++ ) + if ( *whsp != ' ' ) + break; + if ( *whsp == 0 ) { + // only whitespace -> command valid + (*cmd_noparam[ tid ].commandfunc)(); + return TRUE; + } else if ( command[ cmdlen ] == ' ' ) { + // excess parameters + CON_AddLine( dont_use_params ); + return TRUE; + } + } + } + + return FALSE; +} + + +// commands corresponding to functions with an arbitrary string parameter ----- +// +struct cmd_customstring_s { + + int commandid; + int (*commandfunc)(char*); +}; + +cmd_customstring_s cmd_customstring[] = { + + { CM_BUILD, Cmd_BuildInfo }, + { CM_PATH_ANIM_INTRO, Cmd_SetPathAnimIntro }, + { CM_PATH_ASTREAM_INTRO, Cmd_SetPathAudioStreamIntro }, + { CM_PATH_ASTREAM_MENU, Cmd_SetPathAudioStreamMenu }, + { CM_PATH_ASTREAM, Cmd_SetPathAudioStreams }, + { CM_WORKINGDIRECTORY, Cmd_SetPathWorkingDirectory }, + { CM_LISTINTCOMMANDS, Cmd_ListIntCommands }, + { CM_LISTSTDCOMMANDS, Cmd_ListStdCommands }, + { CM_LISTEXTCOMMS, Cmd_ListExternalCommands }, + { CM_DISPLAY, Cmd_DisplayText }, + { CM_CAT, Cmd_CatExternalCommands }, + { CM_GAMELOOPBATCH, Cmd_SetGameLoopBatchName }, + { CM_SAY, Cmd_SayText }, + { CM_SET_MACRO, Cmd_SetTextMacro }, + { CM_LISTDATA, Cmd_ListDataTable }, + { CM_VID_SETMODE, Cmd_SetVidMode }, + { CM_CONNECT, Cmd_Connect }, + { CM_WRITESTRING, Cmd_WriteText }, + { CM_CREATE, Cmd_Create }, + { CM_OPEN, Cmd_Open }, + { CM_RECDEM, Cmd_Recdem }, + { CM_RECORD, Cmd_Record }, + { CM_APPEND, Cmd_Append }, + { CM_PLAYDEMO, Cmd_PlayBinaryDemoFile }, + { CM_LOAD, Cmd_ExecLoadCommand }, + { CM_DEFSHADER, Cmd_DefShader }, + { CM_SETSHADER, Cmd_SetShader }, + { CM_COLANIM, Cmd_DefColAnim }, + { CM_FACEINFO, Cmd_FaceInfo }, +}; + +#define NUM_CMDS_CUSTOMSTRING CALC_NUM_ARRAY_ENTRIES( cmd_customstring ) + + +// commands corresponding to functions taking an arbitrary string parameter --- +// +int CheckCmdsCustomString( const char *command ) +{ + ASSERT( command != NULL ); + + //NOTE: + // this function returns TRUE if a valid command + // has been detected and executed. it returns + // FALSE if no valid command has been detected + // and the command string therefore needs + // further processing by the main dispatcher. + + //NOTE: + // a space as delimiter behind a command is not + // enforced by this function. that is, the supplied + // parsing functions can grab an entire domain + // (set of commands starting with the same characters). + // but this also means they have to ensure the delimiter + // is indeed there if there should be only one command. + + //NOTE: + // due to the semantics of this function and most parsing + // functions it calls, most "custom string" commands reserve + // an entire domain. that is, after this function no + // commands starting with the same characters as a + // "custom string" command will be recognized. + // this behavior also depends on HANDLE_COMMAND_DOMAIN(). + + // check for commands in "custom string" table + for ( unsigned int tid = 0; tid < NUM_CMDS_CUSTOMSTRING; tid++ ) { + + const char *cmdstr = CMSTR( cmd_customstring[ tid ].commandid ); + int cmdlen = CMLEN( cmd_customstring[ tid ].commandid ); + + if ( strncmp( command, cmdstr, cmdlen ) == 0 ) { + + ASSERT( cmd_customstring[ tid ].commandfunc != NULL ); + return (*cmd_customstring[ tid ].commandfunc)( (char *) command + cmdlen ); + } + } + + return FALSE; +} + + +// user command handling ------------------------------------------------------ +// +PRIVATE user_command_s user_commands_default[ 32 ]; +PUBLIC user_command_s* user_commands = user_commands_default; +PUBLIC int num_user_commands = 0; +PRIVATE int max_user_commands = 32; + + +// check user commands -------------------------------------------------------- +// +int CheckCmdsUserDefined( const char *command ) +{ + ASSERT( command != NULL ); + + //NOTE: + // the semantics of this function is basically + // the same as for CheckCmdsCustomString(). + + //NOTE: + // this function will be called very early in + // the sequence of command comparsions. thus, + // it can override most other commands. the + // callback functions have to be very careful + // not to block entire domains without any reason. + + // check for commands in user commands table + for ( int cid = 0; cid < num_user_commands; cid++ ) { + + const char *cmdstr = user_commands[ cid ].command; + int cmdlen = user_commands[ cid ].commlen; + + if ( strncmp( command, cmdstr, cmdlen ) == 0 ) { + + ASSERT( user_commands[ cid ].execute != NULL ); + return (*user_commands[ cid ].execute)( (char *) command + cmdlen ); + } + } + + return FALSE; +} + + +// register a new user-defined command ---------------------------------------- +// +int CON_RegisterUserCommand( user_command_s *regcom ) +{ + //NOTE: + //CAVEAT: + // the supplied command string is not copied + // by this function. thus, the caller MUST ENSURE + // that this string is available indefinitely. + // (e.g., allocated statically.) + + //NOTE: + // the commlen field need not be valid, it will be + // set by this function. (in the original struct!) + + ASSERT( regcom != NULL ); + ASSERT( regcom->command != NULL ); + ASSERT( regcom->execute != NULL ); + ASSERT( regcom->numparams >= 0 ); + ASSERT( num_user_commands <= max_user_commands ); + + // expand table memory if already used up + if ( num_user_commands == max_user_commands ) { + + // expand exponentially + int newtabsize = max_user_commands * 2; + + // alloc new table + user_command_s *newlist = (user_command_s *) ALLOCMEM( sizeof( user_command_s ) * newtabsize ); + if ( newlist == NULL ) { + ASSERT( 0 ); + return FALSE; + } + + // set new size + max_user_commands = newtabsize; + + // move old table + memcpy( newlist, user_commands, sizeof( user_command_s ) * num_user_commands ); + if ( user_commands != user_commands_default ) + FREEMEM( user_commands ); + user_commands = newlist; + } + + // append new command + regcom->commlen = strlen( regcom->command ); + ASSERT( num_user_commands < max_user_commands ); + user_commands[ num_user_commands++ ] = *regcom; + + return TRUE; +} + +// replace the entry for an already registered user-defined command ----------- +// +int CON_ReplaceUserCommand( user_command_s* repcom ) +{ + //NOTE: + //CAVEAT: + // the supplied command string is not copied + // by this function. thus, the caller MUST ENSURE + // that this string is available indefinitely. + // (e.g., allocated statically.) + + //NOTE: + // the commlen field need not be valid, it will be + // set by this function. (in the original struct!) + + ASSERT( repcom != NULL ); + ASSERT( repcom->command != NULL ); + ASSERT( repcom->execute != NULL ); + ASSERT( repcom->numparams >= 0 ); + + for( int user_command_index = 0; user_command_index < num_user_commands; user_command_index++ ) { + + // check for equal command string + if( stricmp( user_commands[ user_command_index ].command , repcom->command ) == 0 ) { + repcom->commlen = strlen( repcom->command ); + user_commands[ user_command_index ] = *repcom; + + return TRUE; + } + } + + return FALSE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( CON_COM ) +{ + +#ifdef PARSEC_DEBUG + + // register "heap" command + user_command_s regcom; + regcom.command = "heap"; + regcom.numparams = 0; + regcom.execute = Cmd_HEAP; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); + +#endif // PARSEC_DEBUG + +} + + + diff --git a/src/parsec/con_conf.cpp b/src/parsec/con_conf.cpp new file mode 100644 index 0000000..d564455 --- /dev/null +++ b/src/parsec/con_conf.cpp @@ -0,0 +1,538 @@ +/* + * PARSEC - Configuration Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1996-1998 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" +#include "vid_defs.h" + +// local module header +#include "con_conf.h" + +// proprietary module headers +#include "con_arg.h" +#include "con_main.h" +#include "con_std.h" +#include "e_color.h" +#include "net_conn.h" +#include "vid_plug.h" + + + +// generic string paste area +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// string constants +static char netsubsys_syntax[] = "syntax: net.subsys []"; + + + +// commands to get/set an rgba color value ------------------------------------ +// +colcomm_s col_comms[] = { + + { "panelback.i", &PanelBackColor, NULL }, + { "paneltext.i", &PanelTextColor, NULL }, + { "flarebase.i", &FlareBaseColor, NULL }, + + { "ambient.i", &LightColorAmbient, NULL }, + { "diffuse.i", &LightColorDiffuse, NULL }, + { "specular.i", &LightColorSpecular, NULL }, + + { NULL, NULL, NULL } +}; + +int num_col_commands = CALC_NUM_ARRAY_ENTRIES( col_comms ) - 1; + + +PRIVATE +int ExecColorCommand(int cmdid) +{ + if ( col_comms[cmdid].func != NULL ) + (*col_comms[cmdid].func)(); + + return TRUE; +} + + +// check single command for color configuration (rgba) ------------------------ +// +INLINE +int CheckColorCommand( int cmdid, char *scan ) +{ + ASSERT( cmdid >= 0 ); + ASSERT( col_comms[ cmdid ].cmd && col_comms[ cmdid ].col ); + ASSERT( scan != NULL ); + + int cmdlen = strlen( col_comms[ cmdid ].cmd ); + ASSERT( ( cmdlen > 1 ) && ( cmdlen < 32 ) ); + + // early exit if wrong prefix + if ( strncmp( scan, col_comms[ cmdid ].cmd, cmdlen - 2 ) != 0 ) + return FALSE; + + // make copy of command to avoid manipulating BSS string + char cmdstr[ 32 ]; + strcpy( cmdstr, col_comms[ cmdid ].cmd ); + + cmdstr[ cmdlen - 2 ] = '\0'; + if ( strcmp( scan, cmdstr ) == 0 ) { + + if ( strtok( NULL, " " ) != NULL ) { + // no arguments must be specified! + return FALSE; + } + + // color command without field specifier displays (R,G,B,A) + sprintf( paste_str, "%s currently is (rgba):", cmdstr ); + CON_AddLine( paste_str ); + sprintf( paste_str, "(%03d,%03d,%03d,%03d):", + col_comms[ cmdid ].col->R, col_comms[ cmdid ].col->G, + col_comms[ cmdid ].col->B, col_comms[ cmdid ].col->A ); + CON_AddLine( paste_str ); + + return TRUE; + } + cmdstr[ cmdlen - 2 ] = '.'; + + int byteconv = col_comms[ cmdid ].col->A; + cmdstr[ cmdlen - 1 ] = 'a'; + if ( CheckSetIntArgBounded( "%d", scan, cmdstr, &byteconv, 0, COLRGBA_FULLYOPAQUE, NULL ) ) { + col_comms[ cmdid ].col->A = byteconv; + return ExecColorCommand(cmdid); + } + + byteconv = col_comms[ cmdid ].col->R; + cmdstr[ cmdlen - 1 ] = 'r'; + if ( CheckSetIntArgBounded( "%d", scan, cmdstr, &byteconv, 0, COLRGBA_FULLBRIGHT, NULL ) ) { + col_comms[ cmdid ].col->R = byteconv; + return ExecColorCommand(cmdid); + } + + byteconv = col_comms[ cmdid ].col->G; + cmdstr[ cmdlen - 1 ] = 'g'; + if ( CheckSetIntArgBounded( "%d", scan, cmdstr, &byteconv, 0, COLRGBA_FULLBRIGHT, NULL ) ) { + col_comms[ cmdid ].col->G = byteconv; + return ExecColorCommand(cmdid); + } + + byteconv = col_comms[ cmdid ].col->B; + cmdstr[ cmdlen - 1 ] = 'b'; + if ( CheckSetIntArgBounded( "%d", scan, cmdstr, &byteconv, 0, COLRGBA_FULLBRIGHT, NULL ) ) { + col_comms[ cmdid ].col->B = byteconv; + return ExecColorCommand(cmdid); + } + + // luminance=(r,g,b) + byteconv = col_comms[ cmdid ].col->G; + cmdstr[ cmdlen - 1 ] = 'l'; + if ( CheckSetIntArgBounded( "%d", scan, cmdstr, &byteconv, 0, COLRGBA_FULLBRIGHT, NULL ) ) { + col_comms[ cmdid ].col->R = byteconv; + col_comms[ cmdid ].col->G = byteconv; + col_comms[ cmdid ].col->B = byteconv; + return ExecColorCommand(cmdid); + } + + return FALSE; +} + + + +// check all commands for color configuration (rgba) -------------------------- +// +int CheckColorConfig( char *scan ) +{ + ASSERT( scan != NULL ); + + // scan list of color commands + for ( int curcmd = 0; col_comms[ curcmd ].cmd; curcmd++ ) { + + if ( CheckColorCommand( curcmd, scan ) ) + return TRUE; + } + + return FALSE; +} + + +// switch to alternate video configuration ------------------------------------ +// +PRIVATE +void SetVideoConfiguration() +{ + // display active video subsystem if no parameter supplied + char *vsys; + if ( ( vsys = strtok( NULL, " " ) ) == NULL ) { + // removed + return; + } + + // check for more than one parameter + if ( strtok( NULL, " " ) != NULL ) { + CON_AddLine( "specify video subsystem with a single word." ); + return; + } + + // string must be copied because it will be destroyed + // if a console script is executed on subsystem switch + strcpy( paste_str, vsys ); + + // try to change to specified video subsystem + if ( VID_PlugInSubsys( vsys ) ) { + strcat( paste_str, " selected as video subsystem." ); + CON_AddLine( paste_str ); + } else { + strcat( paste_str, " video subsystem not available or invalid." ); + CON_AddLine( paste_str ); + } +} + + +// display name of currently active protocol --------------------------------- +// +void DisplayCurrentNetSubsys() +{ + // fetch string describing currently active protocol + const char *prot = NET_GetCurrentProtocolName(); + + // display + sprintf( paste_str, "current networking subsystem: %s", prot); + CON_AddLine( paste_str ); +} + + +// switch to alternate network configuration (protocol/packet api) ------------ +// +PRIVATE +void SetNetworkConfiguration() +{ + //NOTE: + //CONCOM: + // net_config ::= 'net.subsys' [] + // protocol ::= 'peer-to-peer' | 'slot-server' | 'game-server' + + //NOTE: + // displays currently active networking subsystem + // if no parameter supplied (protocol/packet-api). + + // fetch protocol + const char *prot = strtok( NULL, " " ); + if ( prot == NULL ) { + DisplayCurrentNetSubsys(); + return; + } + + // check for more than one parameter + if ( strtok( NULL, " " ) != NULL ) { + CON_AddLine( netsubsys_syntax ); +// return; + } + + //FIXME: at startup the init messages are displayed twice due to net.conf in parsecrc.con + + // check for idempotent network configuration change + const char* cur_prot = NET_GetCurrentProtocolName(); + if ( strncmp( cur_prot, prot, strlen( prot ) ) != 0 ) { + + // try to change to specified networking subsystem + if ( NET_SwitchNetSubsys( prot ) ) { + prot = NET_GetCurrentProtocolName(); + MSGOUT( "%s selected.", prot ); + } else { + if ( prot == NULL ) + prot = NET_GetCurrentProtocolName(); + MSGOUT( "%s not available or invalid.", prot ); + //FIXME: CON_AddLine( netsubsys_syntax ); + } + } +} + + +// set audio configuration (music, sfx ) ------------------------------------- +// +PRIVATE +void SetAudioConfiguration() +{ + //NOTE: + //CONCOM: + // audio_config ::= 'aud.conf' [conf_spec] [conf_spec] + // conf_spec ::= 'off' | 'music' | 'sfx' + + //NOTE: + // displays currently audio configuration + // if no parameter supplied. + + if ( SoundDisabled ) { + return; + } + + // fetch first option + char *option1 = strtok( NULL, " " ); + if ( option1 == NULL ) { + + int cursetting = 0x00; + if ( Op_SoundEffects ) + cursetting |= 0x01; + if ( Op_Music ) + cursetting |= 0x02; + + switch ( cursetting ) { + + case 0x00: + sprintf( paste_str, "current audio configuration: off" ); + break; + + case 0x01: + sprintf( paste_str, "current audio configuration: sound effects only" ); + break; + + case 0x02: + sprintf( paste_str, "current audio configuration: music only" ); + break; + + case 0x03: + sprintf( paste_str, "current audio configuration: music and sound effects" ); + break; + + } + + CON_AddLine( paste_str ); + return; + } + + int cursetting = 0x00; + + if ( stricmp( option1, "music" ) == 0 ) { + + cursetting |= 0x02; + + } else if ( stricmp( option1, "sfx" ) == 0 ) { + + cursetting |= 0x01; + + } else if ( stricmp( option1, "off" ) == 0 ) { + + cursetting |= 0x00; + } + + // fetch second option + char *option2 = strtok( NULL, " " ); + + if ( option2 != NULL ) { + if ( stricmp( option2, "music" ) == 0 ) { + + cursetting |= 0x02; + + } else if ( stricmp( option2, "sfx" ) == 0 ) { + + cursetting |= 0x01; + + } else if ( stricmp( option2, "off" ) == 0 ) { + + cursetting |= 0x00; + } + } + + // determine new setting + Op_SoundEffects = ( ( cursetting & 0x01 ) != 0x00 ); + Op_Music = ( ( cursetting & 0x02 ) != 0x00 ); + + // start/stop according to setting + switch ( cursetting ) { + + //NOTE: + // the sequence of AUDs_CloseMenuSound() and AUDs_StopAudioStream() + // must not be changed, or the stream active flag will wrongly stick. + + case 0x00: + //AUDs_CDStop(); + AUDs_CloseMenuSound(); + AUDs_StopAudioStream(); + break; + + case 0x01: + //AUDs_CDStop(); + AUDs_CloseMenuSound(); + AUDs_StopAudioStream(); + break; + + case 0x02: + if ( aud_do_open_menu_sound_on_aud_conf ) + AUDs_OpenMenuSound(); + break; + + case 0x03: + if ( aud_do_open_menu_sound_on_aud_conf ) + AUDs_OpenMenuSound(); + break; + + default: + ASSERT( 0 ); + } +} + + +// set input configuration (mouse, joy) -------------------------------------- +// +PRIVATE +void SetInputConfiguration() +{ + //NOTE: + //CONCOM: + // input_config ::= 'inp.conf' [conf_spec] [conf_spec] + // conf_spec ::= 'off' | 'joystick' | 'mouse' + + //NOTE: + // displays currently input configuration + // if no parameter supplied. + + // fetch first option + char *option = strtok( NULL, " " ); + if ( option == NULL ) { + + int cursetting = 0x00; + if ( Op_Joystick ) + cursetting |= 0x01; + if ( Op_Mouse ) + cursetting |= 0x02; + + switch ( cursetting ) { + + case 0x00: + sprintf( paste_str, "current input configuration: off (keyboard only)" ); + break; + + case 0x01: + sprintf( paste_str, "current input configuration: joystick and keyboard" ); + break; + + case 0x02: + sprintf( paste_str, "current input configuration: mouse and keyboard" ); + break; + } + + CON_AddLine( paste_str ); + return; + } + + int cursetting = 0x00; + + if ( stricmp( option, "mouse" ) == 0 ) { + + cursetting |= 0x02; + + } else if ( stricmp( option, "joystick" ) == 0 ) { + + cursetting |= 0x01; + + } else if ( stricmp( option, "off" ) == 0 ) { + + cursetting |= 0x00; + } + + // ensure joystick is available + if ( ( cursetting & 0x01 ) && JoystickDisabled ) { + cursetting &= ~0x01; + } + + // determine new setting + Op_Joystick = ( ( cursetting & 0x01 ) != 0x00 ); + Op_Mouse = ( ( cursetting & 0x02 ) != 0x00 ); +} + + +// commands to do on-the-fly configuration ------------------------------------ +// +struct configcomm_s { + + int cmdid; + void (*func)(); +}; + +configcomm_s config_comms[] = { + + { CM_VID_SUBSYS, SetVideoConfiguration }, + { CM_NET_SUBSYS, SetNetworkConfiguration }, + { CM_AUD_CONF, SetAudioConfiguration }, + { CM_INP_CONF, SetInputConfiguration }, + + { 0, NULL } +}; + + +// check single command for on-the-fly configuration -------------------------- +// +INLINE +int CheckConfigCommand( int cmdid, char *scan ) +{ + ASSERT( cmdid >= 0 ); + ASSERT( config_comms[ cmdid ].func ); + ASSERT( scan != NULL ); + + if ( strcmp( scan, CMSTR( config_comms[ cmdid ].cmdid ) ) == 0 ) { + + if ( config_comms[ cmdid ].func != NULL ) + (*config_comms[ cmdid ].func)(); + + return TRUE; + } + + return FALSE; +} + + +// check configuration command ------------------------------------------------ +// +int CheckConfigCommand( char *scan ) +{ + ASSERT( scan != NULL ); + + for ( int curcmd = 0; config_comms[ curcmd ].func; curcmd++ ) { + + if ( CheckConfigCommand( curcmd, scan ) ) + return TRUE; + } + + return FALSE; +} + + + diff --git a/src/parsec/con_ext.cpp b/src/parsec/con_ext.cpp new file mode 100644 index 0000000..c858133 --- /dev/null +++ b/src/parsec/con_ext.cpp @@ -0,0 +1,1193 @@ +/* + * PARSEC - External Commands + * + * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:23 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1996-2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// local module header +#include "con_ext.h" + +// proprietary module headers +#include "con_act.h" +#include "con_aux.h" +#include "con_list.h" +#include "con_main.h" +#include "con_std.h" +#include "con_vald.h" +#include "e_demo.h" +#include "e_record.h" +#include "e_replay.h" +#include "sys_file.h" +#include "sys_path.h" + + + +// maximum depth of recursion in command batch files +#define MAX_BATCH_REC_DEPTH 16 + +// special eof needed in package console scripts +#define PACKAGE_CON_EOF ";eof" +#define PACKAGE_CON_EOF_LEN 4 + +// generic string paste area +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + +// string constants +static char con_extension[] = CON_FILE_EXTENSION; +static char invalid_batch_name[]= "invalid name specifier."; +static char recursion_canceled[]= "command canceled due to recursion."; +static char recursion_maxdepth[]= "maximum recursion depth reached."; +static char replaying_script[] = "replay in progress (script)."; +static char replaying_binary[] = "replay in progress (binary)."; +static char no_replay[] = "no replay in progress."; +static char stopped_replay[] = "replay has been stopped."; +static char record_disallowed[] = "recording not allowed (object camera is active)."; + +static char con_file_wldcard1[] = "*" CON_FILE_EXTENSION; +static char con_file_wldcard2[] = REFCON_COMMANDS_DIR "*" CON_FILE_EXTENSION; +static char con_file_wldcard3[] = STDCON_COMMANDS_DIR "*" CON_FILE_EXTENSION; +static char con_file_wldcard4[] = RECORD_COMMANDS_DIR "*" CON_FILE_EXTENSION; + +// name of batch command file to execute on every gameloop start +char gameloop_start_script[ PATH_MAX + 1 ] = ""; + +// list of external commands +char external_commands[ MAX_EXTERNAL_COMMANDS + 1 ][ COMMAND_NAME_ALLOC_LEN + 1 ]; +int external_command_types[ MAX_EXTERNAL_COMMANDS + 1 ]; +int num_external_commands = 0; + +// external batch execution vars +int processing_batch = 0; // flag that commands are called from batch +int idle_reclevel = 0; // level of recursion idle wait stalled execution on +int rec_depth = 0; // current level of recursion + +// action commands not allowed? +int preempt_action_commands = FALSE; + +// batch execution recursive call stack +static int extcom_on_level[ MAX_BATCH_REC_DEPTH + 1 ]; +static FILE *fp_for_level[ MAX_BATCH_REC_DEPTH + 1 ]; + +// log file (created command batch) +FILE *log_fp; +char log_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; +int log_commands = 0; + +// recording file +static char record_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; + +// packet recording/replay file names +char packet_record_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; +char packet_replay_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; + +// single command line +static char com_line[ MAX_CONSOLE_LINE_LENGTH + 1 ]; + +// cat feature variables +static char cat_name[ MAX_CONSOLE_LINE_LENGTH + 1 ]; +static int cat_pos; + +// current active mod name +PUBLIC char* mod_names[ MAX_REGISTERED_MODS ]; +PUBLIC int mod_numnames = 0; +PUBLIC int mod_override = FALSE; + + +// acquire scripts located in mod directories --------------------------------- +// +PRIVATE +void AcquireModScripts() +{ + for ( int mod = 0; mod < mod_numnames; mod++ ) { + + char *path = (char *) ALLOCMEM( + strlen( mod_names[ mod ] ) + strlen( con_file_wldcard1 ) + 2 ); + if ( path == NULL ) { + OUTOFMEM( 0 ); + } + + strcpy( path, mod_names[ mod ] ); + strcat( path, "/" ); + strcat( path, con_file_wldcard1 ); + + char *npath = SYSs_ProcessPathString( path ); + SYSs_AcquireScriptPath( npath, COMTYPE_MODIFICATION, mod_names[ mod ] ); + + FREEMEM( path ); + } +} + + +// build list of externally available commands -------------------------------- +// +void BuildExternalCommandList() +{ + //NOTE: + // the sequence of paths scanned in this function mostly determines the + // display order of console scripts (ls command, tab completion, ...). + // the actual precedence of scripts is determined by the search order + // in OpenScript(). for consistency, the two orders should be the same. + + num_external_commands = 0; + + SYS_AcquirePackageScripts( COMTYPE_PACKAGE ); + + if ( mod_override ) { + AcquireModScripts(); + } + + SYSs_AcquireScriptPath( con_file_wldcard1, COMTYPE_ROOT, NULL ); + SYSs_AcquireScriptPath( con_file_wldcard2, COMTYPE_REFERENCE, NULL ); + SYSs_AcquireScriptPath( con_file_wldcard3, COMTYPE_STANDARD, NULL ); + SYSs_AcquireScriptPath( con_file_wldcard4, COMTYPE_RECORDING, NULL ); + + if ( !mod_override ) { + AcquireModScripts(); + } +} + + +// check if string is valid external command ---------------------------------- +// +int CheckExternalCommand( char *com ) +{ + ASSERT( com != NULL ); + + //NOTE: + // command script directories are only scanned once. therefore, + // new commands copied into a directory while the game is still + // running will not be noticed until next startup or explicit + // rescanning via the "rescan" command. + + // to ensure scripts with explicitly specified paths work + com = SYSs_ProcessPathString( com ); + + // scan list in memory (no directory rescanning!!) + int cid = -1; + for ( int eid = 0; eid < num_external_commands; eid++ ) { + ASSERT( external_commands[ eid ] != NULL ); + if ( stricmp( external_commands[ eid ], com ) == 0 ) { + cid = eid; + break; + } + } + + // return command number + 1 (thus 0 means command is invalid) + return ( cid + 1 ); +} + + +// insert command into log file (command batch) ------------------------------- +// +int InsertCommandLog( char *command ) +{ + ASSERT( command != NULL ); + + if ( log_commands && ( strcmp( command, CMSTR( CM_CLOSE ) ) != 0 ) ) { + // append command to currently open logfile + fprintf( log_fp, "%s\n", command ); + return TRUE; + } + + return FALSE; +} + + +// search all console script paths and open batch if it exists ---------------- +// +PRIVATE +FILE *OpenScript( char *script ) +{ + ASSERT( script != NULL ); + + //NOTE: + // the sequence of paths scanned in this function determines the + // precedence of console scripts of the same name but located in + // different directories. + + //NOTE: + // the path search sequence is: + // 1. data package + // 2. root (local) directory + // 3. reference directory (refs) + // 4. standard directory (cons) + // 5. recording directory (recs) + + //NOTE: + // to avoid inconsistencies the search order in E_RECORD::LoadPacket() + // and E_DEMO::DEMO_BinaryOpenDemo() should be consistent + // with the search order used here. + + FILE *fp = NULL; + + strcpy( paste_str, script ); + strcat( paste_str, con_extension ); + + // to ensure scripts with explicitly specified paths work + char *path = SYSs_ProcessPathString( paste_str ); + + if ( !AUX_DISABLE_PACKAGE_SCRIPTS ) { + + // try to read from package first + if ( ( fp = SYS_fopen( path, "r" ) ) != NULL ) { + return fp; + } + } + + // search root (local) directory + if ( ( fp = fopen( path, "r" ) ) != NULL ) { + return fp; + } + + strcpy( paste_str, REFCON_COMMANDS_DIR ); + strcat( paste_str, script ); + strcat( paste_str, con_extension ); + + // search reference directory (refs) + if ( ( fp = fopen( paste_str, "r" ) ) != NULL ) { + return fp; + } + + strcpy( paste_str, STDCON_COMMANDS_DIR ); + strcat( paste_str, script ); + strcat( paste_str, con_extension ); + + // search standard directory (cons) + if ( ( fp = fopen( paste_str, "r" ) ) != NULL ) { + return fp; + } + + strcpy( paste_str, RECORD_COMMANDS_DIR ); + strcat( paste_str, script ); + strcat( paste_str, con_extension ); + + // search recording directory (recs) + return fopen( paste_str, "r" ); +} + + +// display content of command batch file -------------------------------------- +// +PRIVATE +void CatExternalCommands_ctd() +{ + int i = 0; + + FILE *fp = OpenScript( cat_name ); + + if ( fp != NULL ) { + + SYS_fseek( fp, cat_pos, SEEK_SET ); + + int packeof = 0; + while ( SYS_fgets( com_line, MAX_CONSOLE_LINE_LENGTH, fp ) != NULL ) { + + // check special package eof + if ( strncmp( com_line, PACKAGE_CON_EOF, PACKAGE_CON_EOF_LEN ) == 0 ) { + packeof = 1; + break; + } + + ProcessExternalLine( com_line ); + CON_AddLine( com_line ); + if ( ++i >= cur_vis_conlines - 1 ) { + break; + } + } + + if ( packeof || SYS_feof( fp ) ) { + CON_ListEndPrompt(); + } else { + CON_ListCtdPrompt(); + cat_pos = SYS_ftell( fp ); + } + + SYS_fclose( fp ); + } +} + + +// display content of command batch file (command "cat") ---------------------- +// +int Cmd_CatExternalCommands( char *cstr ) +{ + ASSERT( cstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( cstr ); + + char *name = strtok( cstr, " " ); + + if ( ( name == NULL ) || ( strtok( NULL, " " ) != NULL ) ) { + CON_AddLine( "syntax: cat