diff --git a/polymer/eduke32/source/sw/Makefile.deps b/polymer/eduke32/source/sw/Makefile.deps new file mode 100644 index 000000000..2b2edd873 --- /dev/null +++ b/polymer/eduke32/source/sw/Makefile.deps @@ -0,0 +1,90 @@ +build_h=$(ENGINE_INC)/build.h $(ENGINE_INC)/compat.h +panel_h=$(SW_INC)/panel.h $(SW_INC)/mytypes.h $(SW_INC)/game.h $(SW_INC)/conpic.h +names2_h=$(SW_INC)/names2.h $(SW_INC)/names.h +game_h=$(SW_INC)/game.h $(SW_INC)/mytypes.h $(MACT_ROOT)/keyboard.h $(SW_INC)/sounds.h $(SW_INC)/settings.h $(SW_INC)/digi.h $(SW_INC)/damage.h $(SW_INC)/inv.h $(SW_INC)/stag.h +tags_h=$(SW_INC)/tags.h $(SW_INC)/jtags.h + +$(SW_OBJ)/actor.$o: $(SW_SRC)/actor.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/weapon.h $(SW_INC)/sprite.h $(SW_INC)/actor.h $(SW_INC)/saveable.h +$(SW_OBJ)/ai.$o: $(SW_SRC)/ai.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ninja.h $(SW_INC)/ai.h $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/net.h $(SW_INC)/saveable.h +$(SW_OBJ)/anim.$o: $(SW_SRC)/anim.c $(build_h) $(SW_INC)/keys.h $(SW_INC)/mytypes.h $(MACT_ROOT)/develop.h $(AUDIOLIB_INC)/fx_man.h $(AUDIOLIB_INC)/music.h $(MACT_ROOT)/scriplib.h $(MACT_ROOT)/file_lib.h $(SW_INC)/gamedefs.h $(MACT_ROOT)/keyboard.h $(MACT_ROOT)/util_lib.h $(MACT_ROOT)/control.h $(SW_INC)/config.h $(SW_INC)/sounds.h $(SW_INC)/function.h $(MACT_ROOT)/animlib.h $(SW_INC)/anim.h $(game_h) $(SW_INC)/colormap.h $(SW_INC)/net.h +$(SW_OBJ)/border.$o: $(SW_SRC)/border.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(SW_INC)/lists.h $(game_h) $(SW_INC)/net.h $(SW_INC)/text.h +$(SW_OBJ)/break.$o: $(SW_SRC)/break.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/break.h $(SW_INC)/sprite.h $(SW_INC)/sector.h $(SW_INC)/light.h $(SW_INC)/weapon.h +$(SW_OBJ)/bunny.$o: $(SW_SRC)/bunny.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/pal.h $(SW_INC)/sprite.h $(SW_INC)/actor.h $(SW_INC)/weapon.h $(SW_INC)/track.h $(SW_INC)/saveable.h +$(SW_OBJ)/cache.$o: $(SW_SRC)/cache.c $(build_h) $(names2_h) $(game_h) $(tags_h) $(SW_INC)/break.h $(SW_INC)/quake.h $(SW_INC)/pal.h $(SW_INC)/cache.h $(SW_INC)/sounds.h $(SW_INC)/net.h +$(SW_OBJ)/cd.$o: $(SW_SRC)/cd.c $(SW_INC)/mytypes.h $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/player.h $(SW_INC)/lists.h $(SW_INC)/warp.h $(SW_INC)/quake.h $(SW_INC)/function.h $(MACT_ROOT)/control.h $(SW_INC)/trigger.h $(SW_INC)/savedef.h $(SW_INC)/menus.h $(SW_INC)/net.h $(SW_INC)/pal.h +$(SW_OBJ)/cheats.$o: $(SW_SRC)/cheats.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/mytypes.h $(MACT_ROOT)/control.h $(SW_INC)/function.h $(SW_INC)/text.h +$(SW_OBJ)/colormap.$o: $(SW_SRC)/colormap.c $(build_h) $(SW_INC)/keys.h $(SW_INC)/pal.h $(game_h) +$(SW_OBJ)/config.$o: $(SW_SRC)/config.c $(build_h) $(SW_INC)/settings.h $(SW_INC)/mytypes.h $(MACT_ROOT)/develop.h $(MACT_ROOT)/scriplib.h $(MACT_ROOT)/file_lib.h $(SW_INC)/gamedefs.h $(MACT_ROOT)/keyboard.h $(MACT_ROOT)/util_lib.h $(SW_INC)/function.h $(MACT_ROOT)/control.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/sounds.h $(SW_INC)/config.h $(SW_INC)/common_game.h $(SW_INC)/_functio.h $(SW_INC)/_config.h +$(SW_OBJ)/console.$o: $(SW_SRC)/console.c $(build_h) $(SW_INC)/mytypes.h $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/player.h $(SW_INC)/lists.h $(SW_INC)/warp.h $(SW_INC)/quake.h $(SW_INC)/function.h $(MACT_ROOT)/control.h $(SW_INC)/trigger.h $(SW_INC)/savedef.h $(SW_INC)/menus.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/weapon.h $(SW_INC)/text.h $(SW_INC)/jsector.h +$(SW_OBJ)/coolg.$o: $(SW_SRC)/coolg.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/sprite.h $(SW_INC)/actor.h $(SW_INC)/weapon.h $(SW_INC)/track.h $(SW_INC)/saveable.h +$(SW_OBJ)/coolie.$o: $(SW_SRC)/coolie.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/sprite.h $(SW_INC)/actor.h $(SW_INC)/track.h $(SW_INC)/weapon.h $(SW_INC)/saveable.h +$(SW_OBJ)/copysect.$o: $(SW_SRC)/copysect.c $(build_h) $(names2_h) $(game_h) $(tags_h) $(SW_INC)/weapon.h $(SW_INC)/sprite.h $(SW_INC)/track.h +$(SW_OBJ)/demo.$o: $(SW_SRC)/demo.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/net.h $(SW_INC)/mytypes.h $(MACT_ROOT)/control.h $(SW_INC)/function.h $(SW_INC)/demo.h $(SW_INC)/player.h $(SW_INC)/menus.h +$(SW_OBJ)/draw.$o: $(SW_SRC)/draw.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/quake.h $(SW_INC)/vis.h $(SW_INC)/jsector.h $(SW_INC)/reserve.h $(SW_INC)/mytypes.h $(MACT_ROOT)/control.h $(SW_INC)/function.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/player.h $(SW_INC)/jtags.h $(SW_INC)/parent.h $(SW_INC)/cache.h $(SW_INC)/text.h $(SW_INC)/menus.h $(SW_INC)/interp.h $(SW_INC)/sector.h +$(SW_OBJ)/eel.$o: $(SW_SRC)/eel.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/actor.h $(SW_INC)/weapon.h $(SW_INC)/track.h $(SW_INC)/saveable.h +$(SW_OBJ)/game.$o: $(SW_SRC)/game.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(SW_INC)/player.h $(SW_INC)/lists.h $(SW_INC)/net.h $(SW_INC)/pal.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/mytypes.h $(SW_INC)/menus.h $(MACT_ROOT)/control.h $(SW_INC)/function.h $(SW_INC)/demo.h $(SW_INC)/cache.h $(SW_INC)/anim.h $(SW_INC)/colormap.h $(SW_INC)/break.h $(SW_INC)/ninja.h $(SW_INC)/light.h $(SW_INC)/track.h $(SW_INC)/jsector.h $(MACT_ROOT)/keyboard.h $(SW_INC)/text.h $(AUDIOLIB_INC)/music.h $(SW_INC)/saveable.h +$(SW_OBJ)/girlninj.$o: $(SW_SRC)/girlninj.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/pal.h $(SW_INC)/player.h $(SW_INC)/net.h $(SW_INC)/actor.h $(SW_INC)/track.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/goro.$o: $(SW_SRC)/goro.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/actor.h $(SW_INC)/track.h $(SW_INC)/saveable.h +$(SW_OBJ)/hornet.$o: $(SW_SRC)/hornet.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/actor.h $(SW_INC)/weapon.h $(SW_INC)/track.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/interp.$o: $(SW_SRC)/interp.c $(SW_INC)/interp.h +$(SW_OBJ)/interpsh.$o: $(SW_SRC)/interpsh.c $(SW_INC)/interp.h +$(SW_OBJ)/inv.$o: $(SW_SRC)/inv.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/pal.h $(SW_INC)/text.h $(SW_INC)/colormap.h $(SW_INC)/player.h +$(SW_OBJ)/jplayer.$o: $(SW_SRC)/jplayer.c $(build_h) $(SW_INC)/mytypes.h $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/player.h $(SW_INC)/lists.h $(SW_INC)/warp.h $(SW_INC)/quake.h $(SW_INC)/function.h $(MACT_ROOT)/control.h $(SW_INC)/trigger.h $(SW_INC)/savedef.h $(SW_INC)/menus.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/bots.h +$(SW_OBJ)/jsector.$o: $(SW_SRC)/jsector.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(SW_INC)/jnames.h $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/player.h $(SW_INC)/sprite.h $(SW_INC)/reserve.h $(SW_INC)/jsector.h $(SW_INC)/jtags.h $(SW_INC)/lists.h $(SW_INC)/pal.h $(SW_INC)/parent.h +$(SW_OBJ)/jweapon.$o: $(SW_SRC)/jweapon.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/break.h $(SW_INC)/quake.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/ai.h $(SW_INC)/weapon.h $(SW_INC)/sprite.h $(SW_INC)/sector.h $(SW_INC)/actor.h $(SW_INC)/saveable.h +$(SW_OBJ)/lava.$o: $(SW_SRC)/lava.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/actor.h $(SW_INC)/track.h +$(SW_OBJ)/light.$o: $(SW_SRC)/light.c $(build_h) $(names2_h) $(game_h) $(SW_INC)/light.h +$(SW_OBJ)/mclip.$o: $(SW_SRC)/mclip.c $(build_h) $(SW_INC)/mytypes.h $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/player.h $(SW_INC)/mclip.h +$(SW_OBJ)/mdastr.$o: $(SW_SRC)/mdastr.c $(build_h) $(SW_INC)/mytypes.h $(SW_INC)/keys.h $(names2_h) $(game_h) +$(SW_OBJ)/menus.$o: $(SW_SRC)/menus.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(SW_INC)/player.h $(SW_INC)/jsector.h $(SW_INC)/reserve.h $(MACT_ROOT)/control.h $(SW_INC)/menus.h $(SW_INC)/sw_strs.h $(SW_INC)/pal.h $(SW_INC)/function.h $(SW_INC)/net.h $(AUDIOLIB_INC)/fx_man.h $(AUDIOLIB_INC)/music.h $(SW_INC)/text.h $(SW_INC)/colormap.h +$(SW_OBJ)/miscactr.$o: $(SW_SRC)/miscactr.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/quake.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/actor.h $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/morph.$o: $(SW_SRC)/morph.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/ai.h $(SW_INC)/player.h $(SW_INC)/saveable.h +$(SW_OBJ)/net.$o: $(SW_SRC)/net.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(tags_h) $(game_h) $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/weapon.h $(SW_INC)/text.h $(SW_INC)/menus.h +$(SW_OBJ)/ninja.$o: $(SW_SRC)/ninja.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/pal.h $(SW_INC)/player.h $(SW_INC)/net.h $(SW_INC)/weapon.h $(SW_INC)/track.h $(SW_INC)/actor.h $(SW_INC)/ninja.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/panel.$o: $(SW_SRC)/panel.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(SW_INC)/lists.h $(game_h) $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/vis.h $(SW_INC)/weapon.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/text.h $(SW_INC)/player.h $(SW_INC)/saveable.h +$(SW_OBJ)/player.$o: $(SW_SRC)/player.c $(build_h) $(SW_INC)/mytypes.h $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/player.h $(SW_INC)/lists.h $(SW_INC)/warp.h $(SW_INC)/quake.h $(SW_INC)/text.h $(SW_INC)/function.h $(MACT_ROOT)/control.h $(SW_INC)/trigger.h $(SW_INC)/savedef.h $(SW_INC)/menus.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/demo.h $(SW_INC)/mclip.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(SW_INC)/ninja.h $(SW_INC)/break.h $(SW_INC)/jsector.h $(SW_INC)/sector.h $(SW_INC)/actor.h $(SW_INC)/colormap.h $(AUDIOLIB_INC)/music.h $(SW_INC)/vis.h $(SW_INC)/track.h $(SW_INC)/interp.h $(SW_INC)/saveable.h +$(SW_OBJ)/predict.$o: $(SW_SRC)/predict.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/net.h +$(SW_OBJ)/quake.$o: $(SW_SRC)/quake.c $(build_h) $(names2_h) $(game_h) $(tags_h) $(SW_INC)/break.h $(SW_INC)/quake.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/ripper.$o: $(SW_SRC)/ripper.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/pal.h $(SW_INC)/actor.h $(SW_INC)/sprite.h $(SW_INC)/track.h $(SW_INC)/saveable.h +$(SW_OBJ)/ripper2.$o: $(SW_SRC)/ripper2.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/pal.h $(SW_INC)/actor.h $(SW_INC)/sprite.h $(SW_INC)/track.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/saveable.h +$(SW_OBJ)/rooms.$o: $(SW_SRC)/rooms.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(SW_INC)/warp.h +$(SW_OBJ)/rotator.$o: $(SW_SRC)/rotator.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(SW_INC)/net.h $(tags_h) $(SW_INC)/sector.h $(SW_INC)/text.h $(SW_INC)/interp.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/rts.$o: $(SW_SRC)/rts.c $(SW_INC)/mytypes.h $(MACT_ROOT)/develop.h $(MACT_ROOT)/util_lib.h $(MACT_ROOT)/file_lib.h $(SW_INC)/_rts.h $(SW_INC)/rts.h $(SW_INC)/cache.h +$(SW_OBJ)/save.$o: $(SW_SRC)/save.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/lists.h $(SW_INC)/interp.h $(SW_INC)/net.h $(SW_INC)/savedef.h $(SW_INC)/jsector.h $(SW_INC)/parent.h $(SW_INC)/reserve.h $(SW_INC)/mfile.h $(SW_INC)/weapon.h $(SW_INC)/cache.h $(SW_INC)/colormap.h $(SW_INC)/player.h $(AUDIOLIB_INC)/fx_man.h $(AUDIOLIB_INC)/music.h $(SW_INC)/saveable.h +$(SW_OBJ)/scrip2.$o: $(SW_SRC)/scrip2.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/parse.h $(SW_INC)/jsector.h $(SW_INC)/parent.h +$(SW_OBJ)/sector.$o: $(SW_SRC)/sector.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/player.h $(SW_INC)/quake.h $(SW_INC)/weapon.h $(SW_INC)/jtags.h $(SW_INC)/net.h $(SW_INC)/break.h $(SW_INC)/track.h $(SW_INC)/sprite.h $(SW_INC)/light.h $(SW_INC)/text.h +$(SW_OBJ)/serp.$o: $(SW_SRC)/serp.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/actor.h $(SW_INC)/track.h $(SW_INC)/sector.h +$(SW_OBJ)/setup.$o: $(SW_SRC)/setup.c $(build_h) $(SW_INC)/keys.h $(game_h) $(SW_INC)/mytypes.h $(MACT_ROOT)/develop.h $(AUDIOLIB_INC)/fx_man.h $(AUDIOLIB_INC)/music.h $(MACT_ROOT)/scriplib.h $(MACT_ROOT)/file_lib.h $(SW_INC)/gamedefs.h $(MACT_ROOT)/keyboard.h $(MACT_ROOT)/util_lib.h $(MACT_ROOT)/control.h $(SW_INC)/config.h $(SW_INC)/sounds.h $(SW_INC)/function.h $(SW_INC)/rts.h +$(SW_OBJ)/skel.$o: $(SW_SRC)/skel.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/actor.h $(SW_INC)/track.h +$(SW_OBJ)/skull.$o: $(SW_SRC)/skull.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/weapon.h $(SW_INC)/actor.h +$(SW_OBJ)/slidor.$o: $(SW_SRC)/slidor.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(SW_INC)/net.h $(tags_h) $(SW_INC)/slidor.h $(SW_INC)/slidor.h $(SW_INC)/sector.h $(SW_INC)/interp.h $(SW_INC)/text.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/sounds.$o: $(SW_SRC)/sounds.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(SW_INC)/mytypes.h $(AUDIOLIB_INC)/fx_man.h $(AUDIOLIB_INC)/music.h $(AUDIOLIB_INC)/cd.h $(MACT_ROOT)/util_lib.h $(SW_INC)/gamedefs.h $(SW_INC)/config.h $(panel_h) $(game_h) $(SW_INC)/sounds.h $(SW_INC)/ai.h $(SW_INC)/net.h $(SW_INC)/cache.h $(SW_INC)/text.h $(SW_INC)/rts.h $(SW_INC)/menus.h +$(SW_OBJ)/spike.$o: $(SW_SRC)/spike.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/saveable.h +$(SW_OBJ)/sprite.$o: $(SW_SRC)/sprite.c $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/warp.h $(SW_INC)/light.h $(SW_INC)/break.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/sounds.h $(SW_INC)/interp.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(SW_INC)/jsector.h $(SW_INC)/text.h $(SW_INC)/slidor.h $(SW_INC)/player.h $(SW_INC)/saveable.h +$(SW_OBJ)/sumo.$o: $(SW_SRC)/sumo.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/quake.h $(SW_INC)/actor.h $(SW_INC)/track.h $(SW_INC)/weapon.h $(SW_INC)/sector.h +$(SW_OBJ)/swconfig.$o: $(SW_SRC)/swconfig.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(SW_INC)/mytypes.h $(MACT_ROOT)/develop.h $(MACT_ROOT)/scriplib.h $(AUDIOLIB_INC)/fx_man.h $(SW_INC)/gamedefs.h $(SW_INC)/common_game.h $(SW_INC)/config.h $(SW_INC)/function.h $(SW_INC)/rts.h +$(SW_OBJ)/sync.$o: $(SW_SRC)/sync.c $(SW_INC)/keys.h $(game_h) $(tags_h) $(names2_h) $(SW_INC)/net.h $(SW_INC)/menus.h +$(SW_OBJ)/text.$o: $(SW_SRC)/text.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(SW_INC)/lists.h $(game_h) $(SW_INC)/pal.h $(SW_INC)/text.h $(SW_INC)/net.h +$(SW_OBJ)/timer.$o: $(SW_SRC)/timer.c $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(AUDIOLIB_INC)/fx_man.h $(AUDIOLIB_INC)/music.h $(SW_INC)/audiofx.h +$(SW_OBJ)/track.$o: $(SW_SRC)/track.c $(build_h) $(names2_h) $(panel_h) $(tags_h) $(SW_INC)/sector.h $(SW_INC)/ai.h $(SW_INC)/player.h $(game_h) $(SW_INC)/net.h $(SW_INC)/sprite.h $(SW_INC)/track.h $(SW_INC)/weapon.h $(SW_INC)/saveable.h +$(SW_OBJ)/vator.$o: $(SW_SRC)/vator.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(SW_INC)/net.h $(tags_h) $(SW_INC)/sector.h $(SW_INC)/interp.h $(SW_INC)/text.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(SW_INC)/saveable.h +$(SW_OBJ)/vis.$o: $(SW_SRC)/vis.c $(build_h) $(names2_h) $(game_h) $(tags_h) $(SW_INC)/break.h $(SW_INC)/quake.h $(SW_INC)/pal.h $(SW_INC)/sprite.h +$(SW_OBJ)/wallmove.$o: $(SW_SRC)/wallmove.c $(build_h) $(names2_h) $(game_h) $(tags_h) $(SW_INC)/weapon.h $(SW_INC)/sprite.h +$(SW_OBJ)/warp.$o: $(SW_SRC)/warp.c $(build_h) $(names2_h) $(panel_h) $(game_h) $(SW_INC)/warp.h +$(SW_OBJ)/weapon.$o: $(SW_SRC)/weapon.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/break.h $(SW_INC)/quake.h $(SW_INC)/net.h $(SW_INC)/pal.h $(SW_INC)/vis.h $(SW_INC)/ai.h $(SW_INC)/weapon.h $(SW_INC)/anim.h $(SW_INC)/damage.h $(SW_INC)/sector.h $(SW_INC)/sprite.h $(SW_INC)/actor.h $(SW_INC)/track.h $(SW_INC)/player.h +$(SW_OBJ)/zilla.$o: $(SW_SRC)/zilla.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/quake.h $(SW_INC)/actor.h $(SW_INC)/track.h $(AUDIOLIB_INC)/fx_man.h +$(SW_OBJ)/zombie.$o: $(SW_SRC)/zombie.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(panel_h) $(game_h) $(tags_h) $(SW_INC)/ai.h $(SW_INC)/pal.h $(SW_INC)/player.h $(SW_INC)/net.h $(SW_INC)/sprite.h $(SW_INC)/weapon.h $(SW_INC)/actor.h $(SW_INC)/track.h +$(SW_OBJ)/saveable.$o: $(SW_SRC)/saveable.c $(ENGINE_INC)/compat.h $(SW_INC)/saveable.h + +$(SW_OBJ)/jnstub.$o: $(SW_SRC)/jnstub.c $(build_h) $(SW_INC)/stag.h $(SW_INC)/keys.h $(names2_h) $(game_h) $(tags_h) $(SW_INC)/pal.h $(ENGINE_INC)/pragmas.h $(ENGINE_INC)/editor.h $(ENGINE_INC)/cache1d.h +$(SW_OBJ)/brooms.$o: $(SW_SRC)/brooms.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(ENGINE_INC)/editor.h +$(SW_OBJ)/bldscript.$o: $(SW_SRC)/bldscript.c $(build_h) $(names2_h) $(game_h) $(SW_INC)/parse.h $(ENGINE_INC)/editor.h $(ENGINE_INC)/cache1d.h +$(SW_OBJ)/jbhlp.$o: $(SW_SRC)/jbhlp.c $(build_h) $(SW_INC)/keys.h $(names2_h) $(game_h) $(ENGINE_INC)/editor.h $(ENGINE_INC)/cache1d.h + +$(SW_OBJ)/game_icon.$o: $(SW_RSRC)/game_icon.c + +$(SW_OBJ)/grpscan.$o: $(SW_SRC)/grpscan.c $(ENGINE_INC)/compat.h $(ENGINE_INC)/baselayer.h $(ENGINE_INC)/scriptfile.h $(ENGINE_INC)/cache1d.h $(ENGINE_INC)/crc32.h $(SW_INC)/grpscan.h +$(SW_OBJ)/gameres.$o: $(SW_RSRC)/gameres.rc $(SW_SRC)/startwin.game.h $(SW_RSRC)/game.bmp $(SW_RSRC)/game_icon.ico +$(SW_OBJ)/buildres.$o: $(SW_RSRC)/buildres.rc $(SW_RSRC)/build.bmp $(SW_RSRC)/game_icon.ico +$(SW_OBJ)/startwin.game.$o: $(SW_SRC)/startwin.game.c $(build_h) $(ENGINE_INC)/winlayer.h $(SW_INC)/grpscan.h +$(SW_OBJ)/startgtk.game.$o: $(SW_SRC)/startgtk.game.c $(build_h) $(ENGINE_INC)/dynamicgtk.h $(ENGINE_INC)/baselayer.h $(SW_INC)/grpscan.h diff --git a/polymer/eduke32/source/sw/gpl-2.0.txt b/polymer/eduke32/source/sw/gpl-2.0.txt new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/polymer/eduke32/source/sw/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/polymer/eduke32/source/sw/rsrc/32/manifest.build.xml b/polymer/eduke32/source/sw/rsrc/32/manifest.build.xml new file mode 100644 index 000000000..6ca56058b --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/32/manifest.build.xml @@ -0,0 +1,41 @@ + + + + + true + + + + BUILD for Shadow Warrior + + + + + + + + + + + + + + + + + + + + diff --git a/polymer/eduke32/source/sw/rsrc/32/manifest.game.xml b/polymer/eduke32/source/sw/rsrc/32/manifest.game.xml new file mode 100644 index 000000000..618517d16 --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/32/manifest.game.xml @@ -0,0 +1,41 @@ + + + + + true + + + + Shadow Warrior + + + + + + + + + + + + + + + + + + + + diff --git a/polymer/eduke32/source/sw/rsrc/64/manifest.build.xml b/polymer/eduke32/source/sw/rsrc/64/manifest.build.xml new file mode 100644 index 000000000..ab8029647 --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/64/manifest.build.xml @@ -0,0 +1,41 @@ + + + + + true + + + + BUILD for Shadow Warrior + + + + + + + + + + + + + + + + + + + + diff --git a/polymer/eduke32/source/sw/rsrc/64/manifest.game.xml b/polymer/eduke32/source/sw/rsrc/64/manifest.game.xml new file mode 100644 index 000000000..bf912242a --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/64/manifest.game.xml @@ -0,0 +1,41 @@ + + + + + true + + + + Shadow Warrior + + + + + + + + + + + + + + + + + + + + diff --git a/polymer/eduke32/source/sw/rsrc/build.bmp b/polymer/eduke32/source/sw/rsrc/build.bmp new file mode 100644 index 000000000..849b1a1db Binary files /dev/null and b/polymer/eduke32/source/sw/rsrc/build.bmp differ diff --git a/polymer/eduke32/source/sw/rsrc/buildres.rc b/polymer/eduke32/source/sw/rsrc/buildres.rc new file mode 100644 index 000000000..aa5308adb --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/buildres.rc @@ -0,0 +1,38 @@ +#include +#include +#include "startwin.editor.h" + +RSRC_ICON ICON "game_icon.ico" +RSRC_BMP BITMAP "build.bmp" + +WIN_STARTWIN DIALOGEX DISCARDABLE 20, 40, 260, 200 +STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE | WS_SYSMENU +CAPTION "Startup" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", WIN_STARTWIN_BITMAP, "STATIC", SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 32, 32 + CONTROL "", WIN_STARTWIN_TABCTL, WC_TABCONTROL, WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 5, 250, 170 + CONTROL "&Start", WIN_STARTWIN_START, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 180, 48, 14 + CONTROL "&Cancel", WIN_STARTWIN_CANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 207, 180, 48, 14 + + CONTROL "", WIN_STARTWIN_MESSAGES, "EDIT", ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VSCROLL, 0, 0, 32, 32 +END + +WIN_STARTWINPAGE_CONFIG DIALOGEX DISCARDABLE 20, 40, 279, 168 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +CAPTION "Dialog" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "&2D Video mode:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 8, 50, 8 + CONTROL "", IDC2DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 6, 80, 56 + CONTROL "&Fullscreen", IDCFULLSCREEN, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 148, 8, 49, 10 + CONTROL "&3D Video mode:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 24, 50, 8 + CONTROL "", IDC3DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 22, 80, 56 + CONTROL "&Always show configuration on start", IDCALWAYSSHOW, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 118, 116, 140, 8 +END + +#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) +1 24 "64/manifest.build.xml" +#else +1 24 "32/manifest.build.xml" +#endif diff --git a/polymer/eduke32/source/sw/rsrc/game.bmp b/polymer/eduke32/source/sw/rsrc/game.bmp new file mode 100644 index 000000000..2f0bf7e74 Binary files /dev/null and b/polymer/eduke32/source/sw/rsrc/game.bmp differ diff --git a/polymer/eduke32/source/sw/rsrc/game_icon.c b/polymer/eduke32/source/sw/rsrc/game_icon.c new file mode 100644 index 000000000..4ddc905b8 --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/game_icon.c @@ -0,0 +1,408 @@ + +#include "compat.h" +#include "sdlappicon.h" + +static uint8_t sdlappicon_pixels[] = { + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0l\342\32" + "\32w\346Zx\251\343\200\275\321\346\253\316\332\346\327\323\334\347\370\346" + "\346\347\377\347\347\347\377\347\347\347\367\350\350\350\344\351\351\351" + "\306\267\333\351\242\235\325\354x\353\353\353'\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0q\354\33\0n\350y\21t\343\267s\246\340\310\342\344\347\365\350\350" + "\350\377\351\351\351\377\351\351\351\377\351\351\351\377\351\351\351\377" + "\351\351\351\377\303\336\351\377\331\344\351\377\351\351\351\377\210\314" + "\350\377\350\350\350\377\324\342\347\377\314\337\347\325\346\346\346o\341" + "\341\341\21\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0l\350!\2n\350\234\1m\347\367G\220\342\310\344\346\350\371\351\351\351" + "\377\352\352\352\377\352\352\352\377\353\353\353\377\353\353\353\377\353" + "\353\353\377\353\353\353\377\353\353\353\377\353\353\353\377\353\353\353" + "\377\267\334\353\377\16\251\352\377\230\322\352\377.\261\351\377\204\314" + "\351\377\350\350\350\377\347\347\347\366\317\340\350\236`\312\3640\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\337\10\0k\345\201\1m\347\366\1m\347\367\212" + "\263\344\315\352\352\352\377\353\353\353\377\353\353\353\377\354\354\354" + "\377\354\354\354\377\355\355\355\377\355\355\355\377\355\355\355\377\355" + "\355\355\377\355\355\355\377\355\355\355\377:\270\355\377\17\253\355\377" + "\1\247\354\377\1\247\354\377\1\246\353\377\7\250\353\377:\266\352\377\215" + "\316\351\377\307\336\350\377\325\342\347\363\345\345\345\201\350\350\350" + "\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0q\350-\1l\347\325\1m\350\377\1n\351\377z\254\344\310\353\353" + "\353\377\354\354\354\377\354\354\354\377\355\355\355\377\356\356\356\377" + "\356\356\356\377\357\357\357\377\357\357\357\377\302\342\357\377\275\340" + "\357\377\346\354\357\377\201\317\357\377\2\251\357\377\1\251\357\377\1\250" + "\356\377\1\250\356\377\1\247\355\377\1\247\354\377\1\247\354\377J\273\353" + "\377\350\351\352\377\351\351\351\377\350\350\350\377\351\351\351\336\352" + "\352\3521\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0n\347_\1m\347\367\1m\350\377\1n\352\377\36|\346\312\354\354\354\377\355" + "\355\355\377\356\356\356\377\356\356\356\377\357\357\357\377\337\353\360" + "\3779\272\360\377g\310\361\377\326\350\361\377\351\357\361\377^\306\361\377" + "\7\254\361\377\1\252\361\377\1\252\361\377\1\252\361\377\1\251\360\377\1" + "\251\360\377\1\251\357\377\1\250\356\377\1\250\356\377\1\247\355\377G\273" + "\354\377\274\335\353\377\352\352\352\377\350\350\350\377\347\347\347\363" + "\346\346\346Z\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0o\350z\1m\347" + "\376\1n\351\377\1n\352\377\1o\353\377\272\320\351\337\355\355\355\377\357" + "\357\357\377\357\357\357\377\360\360\360\377\361\361\361\377\362\362\362" + "\377\347\356\362\377\325\352\363\3778\274\363\377`\307\363\377t\316\364\377" + "\1\254\364\377\1\254\363\377\27\262\363\377r\315\363\377\247\334\362\377" + "\206\322\362\377!\264\361\377\1\251\360\377\1\251\357\377;\272\357\377\235" + "\326\355\377\246\330\354\377\223\321\353\377\265\332\352\377\351\351\351" + "\377\347\347\347\376\351\351\351\202\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0m\351" + "u\1m\347\377\1n\351\377\1n\352\377\1o\354\377\21w\351\325\356\356\356\377" + "\357\357\357\377\360\360\360\377\361\361\361\377\362\362\362\377\363\363" + "\363\377\364\364\364\377\364\364\364\377\365\365\365\377\361\364\365\377" + "\276\346\366\377'\270\366\377\1\256\366\377\40\266\366\377\342\357\365\377" + "\365\365\365\377\364\364\364\377\364\364\364\377\345\357\363\3773\272\362" + "\377\1\252\361\377\313\346\360\377\356\357\357\377\326\347\356\377\355\355" + "\355\377\354\354\354\377\352\352\352\377\351\351\351\377\347\347\347\377" + "\352\352\352x\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0m\346[\1m\347\375\1n\351\377\1n\352\377\1o" + "\354\377\1p\355\377P\230\352\303\360\360\360\377\361\361\361\377\362\362" + "\362\377\363\363\363\377\364\364\364\377\365\365\365\377\366\366\366\377" + "\366\366\366\377\367\367\367\377\367\367\367\377\370\370\370\377S\307\370" + "\377\1\257\370\377\227\334\370\377\367\367\367\377\367\367\367\377\366\366" + "\366\377\366\366\366\377\365\365\365\377\315\351\364\377\2\254\363\3774\272" + "\362\377`\306\361\377\307\344\360\377\357\357\357\377\355\355\355\377\354" + "\354\354\377\352\352\352\377\351\351\351\377\347\347\347\375\350\350\350" + "Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0p\3440\1m\347\365\1n\351\377\1n\352\377\1o\354\377\1p\355\377\1p\357\377" + "\201\263\354\307\361\361\361\377\363\363\363\377\364\364\364\377\365\365" + "\365\377\366\366\366\377\367\367\367\377\370\370\370\377\364\367\370\377" + "t\322\371\377\212\330\371\377U\311\372\377\1\260\372\377\1\260\372\377\300" + "\351\372\377\371\371\371\377\371\371\371\377\370\370\370\377\370\370\370" + "\377\367\367\367\377\366\366\366\377\32\265\365\377\13\257\364\377\331\353" + "\363\377\263\337\361\377\360\360\360\377\357\357\357\377\355\355\355\377" + "\354\354\354\377\352\352\352\377\351\351\351\377\347\347\347\367\344\344" + "\3440\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\337\10\1" + "m\350\332\1m\350\377\1n\352\377\1o\354\377\1p\355\377\1p\357\377\1q\360\377" + "\221\275\357\312\363\363\363\377\364\364\364\377\366\366\366\377\367\367" + "\367\377\370\370\370\377\371\371\371\377\372\372\372\377\372\372\372\377" + "\373\373\373\377\373\373\373\377\364\372\374\377\36\273\374\377\1\262\374" + "\377\237\340\374\377\373\373\373\377\373\373\373\377\372\372\372\377\372" + "\372\372\377\371\371\371\377\362\366\370\377\7\260\367\377;\277\366\377\364" + "\364\364\377\363\363\363\377\362\362\362\377\360\360\360\377\357\357\357" + "\377\355\355\355\377\354\354\354\377\352\352\352\377\350\350\350\377\347" + "\347\347\326\377\377\377\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0m\350\203\1m\350\377\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\360" + "\377\1r\362\377\202\266\360\316\365\365\365\377\366\366\366\377\367\367\367" + "\377\371\371\371\377\372\372\372\377\373\373\373\377\374\374\374\377\374" + "\374\374\377\375\375\375\377\362\372\375\377\376\376\376\377m\323\376\377" + "\1\263\376\377*\277\376\377\361\371\375\377\375\375\375\377\374\374\374\377" + "\374\374\374\377\373\373\373\377\230\336\372\377\1\260\371\377\202\324\367" + "\377\366\366\366\377\365\365\365\377\363\363\363\377\362\362\362\377\360" + "\360\360\377\357\357\357\377\355\355\355\377\353\353\353\377\351\351\351" + "\377\350\350\350\377\350\350\350\205\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0p\347\40\1m\347\367\1n\351\377\1o\353\377\1o\354\377\1p\356\377\1q" + "\360\377\1q\361\377\1r\363\377`\245\363\332\366\366\366\377\370\370\370\377" + "\371\371\371\377\372\372\372\377\373\373\373\377\374\374\374\377\375\375" + "\375\377\277\353\376\377\377\377\377\377\346\370\377\377\377\377\377\377" + "\233\342\377\377\1\264\377\377\1\264\377\3778\304\377\377\303\355\377\377" + "\355\371\376\377\336\364\375\377\204\330\374\377\10\263\373\377\1\260\372" + "\3770\275\371\377\370\370\370\377\366\366\366\377\365\365\365\377\363\363" + "\363\377\361\361\361\377\352\356\360\377\275\340\356\377\354\354\354\377" + "\353\353\353\377\351\351\351\377\347\347\347\364\352\352\352\30\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\2m\347\237\1m\350\377\1n\352\377\1o\354\377\1p\355" + "\377\1p\357\377\1q\361\377\1r\363\377\1s\364\377)\210\365\356\370\370\370" + "\377\371\371\371\377\373\373\373\377\374\374\374\377\375\375\375\377\376" + "\376\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\346\370\377\377\21\271\377\377\1\264\377\377\1\264\377" + "\377\1\264\377\377\1\264\377\377\1\264\377\377\1\263\376\377\1\263\375\377" + "\1\262\374\377\2\261\373\377\331\357\371\377\370\370\370\377\366\366\366" + "\377\364\364\364\377\363\363\363\377\361\361\361\377\357\357\357\377\355" + "\355\355\377\354\354\354\377\352\352\352\377\350\350\350\377\347\347\347" + "\224\0\0\0\0\0\0\0\0\0\0\0\0\0j\352\30\1l\350\372\1n\351\377\1o\353\377\1" + "p\355\377\1p\357\377\1q\360\377\1r\362\377\1s\364\377\1t\366\377\2u\367\377" + "\333\351\371\377\373\373\373\377\374\374\374\377\375\375\375\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\276\354\377\377\1\264\377" + "\377\1\264\377\377\1\264\377\377\1\264\377\377\1\264\377\377\1\264\377\377" + "\1\264\377\377\1\263\375\377\1\262\374\377\205\331\373\377\371\371\371\377" + "\367\367\367\377\366\366\366\377\364\364\364\377\362\362\362\377\360\360" + "\360\377\357\357\357\377\355\355\355\377\353\353\353\377\351\351\351\377" + "\347\347\347\367\350\350\350\26\0\0\0\0\0\0\0\0\0n\350y\1m\350\377\1n\352" + "\377\1o\354\377\1p\356\377\1p\357\377\1q\361\377\1r\363\377\1s\365\377\1" + "t\367\377\1u\371\377r\261\372\377\374\374\374\377\375\375\375\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\307\357" + "\377\377~\331\377\377\244\344\377\377\1\264\377\377\1\264\377\377\1\264\377" + "\377\1\264\377\377\1\264\377\377\1\264\377\377\1\263\375\377\27\270\374\377" + "\352\365\372\377\371\371\371\377\367\367\367\377\365\365\365\377\363\363" + "\363\377\361\361\361\377\357\357\357\377\356\356\356\377\354\354\354\377" + "\352\352\352\377\350\350\350\377\350\350\350|\0\0\0\0\0\0\0\0\1m\350\320" + "\1n\351\377\1o\353\377\1o\354\377\1p\356\377\1q\360\377\1r\362\377\1s\364" + "\377\1t\366\377\1u\370\377\1v\372\377\12{\373\377\336\355\375\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377l\323\377\377\353\371\377\377\377\377\377\377<\305\377\377\1\264" + "\377\377\1\264\377\377\1\264\377\377\1\264\377\377\1\264\377\377\25\272\377" + "\377_\316\375\377f\317\373\377\372\372\372\377\370\370\370\377\366\366\366" + "\377\364\364\364\377\362\362\362\377\360\360\360\377\356\356\356\377\354" + "\354\354\377\353\353\353\377\351\351\351\377\350\350\350\322\0\0\0\0\0k\346" + "\37\1m\347\376\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\361\377\1r" + "\363\377\1s\365\377\1t\367\377\1u\371\377\1v\373\377\1w\374\377H\235\376" + "\377\375\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377V\315\377\377\373\376\377\377\377\377\377\377\201\332" + "\377\377\1\264\377\377\1\264\377\377\1\264\377\377\1\264\377\377\1\264\377" + "\377\227\340\377\377\372\375\376\377T\313\374\377\372\373\373\377\371\371" + "\371\377\367\367\367\377\365\365\365\377\363\363\363\377\361\361\361\377" + "\357\357\357\377\355\355\355\377\353\353\353\377\351\351\351\377\347\347" + "\347\376\347\347\347\40\0l\347a\1m\350\377\1n\352\377\1o\354\377\1p\356\377" + "\1q\360\377\1r\362\377\1s\364\377\1t\366\377\1u\370\377\1v\372\377\1w\374" + "\377\1w\375\377\1x\377\377\177\273\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\241\343\377\377\1\264\377\377\33\274\377\377\301\355\377" + "\377\3\265\377\377\7\266\377\377\363\373\377\377\377\377\377\377\375\375" + "\375\377\374\374\374\377\372\372\372\377\370\370\370\377\366\366\366\377" + "\364\364\364\377\362\362\362\377\360\360\360\377\356\356\356\377\354\354" + "\354\377\352\352\352\377\350\350\350\377\350\350\350d\2m\350\230\1m\350\377" + "\1n\352\377\1o\354\377\1p\356\377\1q\360\377\1r\362\377\1s\364\377\1t\366" + "\377\1u\370\377\1v\372\377\1w\374\377\1x\376\377\1x\377\377\1x\377\377\222" + "\305\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\255\347\377\377\377\377\377\377\235\342\377\377\1\264\377\377" + "\261\350\377\377\377\377\377\377\40\275\377\377F\310\377\377\377\377\377" + "\377\377\377\377\377\376\376\376\377\374\374\374\377\372\372\372\377\370" + "\370\370\377\366\366\366\377\364\364\364\377\362\362\362\377\360\360\360" + "\377\356\356\356\377\354\354\354\377\352\352\352\377\350\350\350\377\350" + "\350\350\230\1m\347\300\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\361" + "\377\1r\363\377\1s\365\377\1t\367\377\1u\371\377\1v\373\377\1w\375\377\1" + "x\377\377\1x\377\377\1x\377\377\2y\377\377\236\314\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\337\366\377\377\377\377\377\377" + "u\326\377\377\32\273\377\377\374\376\377\377\377\377\377\377*\300\377\377" + "\222\337\377\377\377\377\377\377\377\377\377\377\377\377\377\377\375\375" + "\375\377\373\373\373\377\371\371\371\377\367\367\367\377\365\365\365\377" + "\363\363\363\377\361\361\361\377\357\357\357\377\355\355\355\377\353\353" + "\353\377\351\351\351\377\350\350\350\300\1l\347\340\1n\351\377\1o\353\377" + "\1p\355\377\1p\357\377\1q\361\377\1r\363\377\1s\365\377\1t\367\377\1u\371" + "\377\1v\373\377\1w\375\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\2" + "y\377\377o\262\377\377\370\373\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377?\306\377\377e\321\377\377\377\377\377\377\377\377\377" + "\377\35\274\377\377\302\355\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\375\375\375\377\373\373\373\377\371\371\371\377\367\367\367\377" + "\365\365\365\377\363\363\363\377\361\361\361\377\357\357\357\377\355\355" + "\355\377\353\353\353\377\351\351\351\377\347\347\347\337\1m\350\366\1n\351" + "\377\1o\353\377\1p\355\377\1p\357\377\1q\361\377\1r\363\377\1s\365\377\1" + "u\370\377\1v\372\377\1w\374\377\1x\376\377\1x\377\377\1x\377\377\1x\377\377" + "\1x\377\377\1x\377\377\1x\377\3772\222\377\377\325\351\377\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\376\377\377\377\14\267\377\377\207\334\377\377\377\377\377\377" + "\377\377\377\377=\306\377\377\322\362\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\376\376\376\377\374\374\374\377\372\372\372\377\370" + "\370\370\377\365\365\365\377\363\363\363\377\361\361\361\377\357\357\357" + "\377\355\355\355\377\353\353\353\377\351\351\351\377\350\350\350\366\1m\347" + "\377\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\361\377\1s\364\377\1" + "t\366\377\1u\370\377\1v\372\377\1w\374\377\1x\376\377\1x\377\377\1x\377\377" + "\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\7{\377\377y\270\377" + "\377\363\371\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\365\374\377\377\1\264\377\377}\330\377\377\377\377\377\377\377" + "\377\377\377l\323\377\377\250\345\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\376\376\376\377\374\374\374\377\372\372\372\377\370\370" + "\370\377\366\366\366\377\364\364\364\377\361\361\361\377\357\357\357\377" + "\355\355\355\377\353\353\353\377\351\351\351\377\350\350\350\377\1m\350\377" + "\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\361\377\1s\364\377\1t\366" + "\377\1u\370\377\1v\372\377\1w\374\377\1x\376\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377" + "\24\202\377\377\201\274\377\377\353\364\377\377\377\377\377\377\377\377\377" + "\377\377\377\377\377\22\271\377\377g\322\377\377\377\377\377\377\377\377" + "\377\377w\327\377\377\250\345\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\376\376\376\377\374\374\374\377\372\372\372\377\370\370\370" + "\377\366\366\366\377\364\364\364\377\361\361\361\377\357\357\357\377\355" + "\355\355\377\353\353\353\377\351\351\351\377\350\350\350\377\1m\350\365\1" + "n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\361\377\1r\363\377\1s\365\377" + "\1u\370\377\1v\372\377\1w\374\377\1x\376\377\1x\377\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\10|\377\377\\\250\377\377\320\346\377\377\377\377\377" + "\377.\301\377\377X\316\377\377\377\377\377\377\377\377\377\377\225\340\377" + "\377d\321\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376\376" + "\376\377\374\374\374\377\372\372\372\377\370\370\370\377\365\365\365\377" + "\363\363\363\377\361\361\361\377\357\357\357\377\355\355\355\377\353\353" + "\353\377\351\351\351\377\350\350\350\365\1l\347\341\1n\351\377\1o\353\377" + "\1p\355\377\1p\357\377\1q\361\377\1r\363\377\1s\365\377\1t\367\377\1u\371" + "\377\1v\373\377\1w\375\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377" + "\1x\377\377\1x\377\377\2y\377\377U\244\377\377B\305\377\377Y\316\377\377" + "\377\377\377\377\377\377\377\377\264\351\377\377\203\333\377\377\377\377" + "\377\377\377\377\377\377\377\377\377\377\375\375\375\377\373\373\373\377" + "\371\371\371\377\367\367\367\377\365\365\365\377\363\363\363\377\361\361" + "\361\377\357\357\357\377\355\355\355\377\353\353\353\377\351\351\351\377" + "\347\347\347\340\1m\347\302\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1" + "q\361\377\1r\363\377\1s\365\377\1t\367\377\1u\371\377\1v\373\377\1w\375\377" + "\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\5\240\377\377<\271\377\377\373\375\377\377\377\377\377" + "\377\221\337\377\377\277\354\377\377\377\377\377\377\377\377\377\377\377" + "\377\377\377\375\375\375\377\373\373\373\377\371\371\371\377\367\367\367" + "\377\365\365\365\377\363\363\363\377\361\361\361\377\357\357\357\377\355" + "\355\355\377\353\353\353\377\351\351\351\377\347\347\347\274\2l\346\216\1" + "m\350\377\1n\352\377\1o\354\377\1p\356\377\1q\360\377\1r\362\377\1s\364\377" + "\1t\366\377\1u\370\377\1v\372\377\1w\374\377\1x\376\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1\232\377" + "\377\1\222\377\377;\227\377\377\346\362\377\377T\314\377\377\336\365\377" + "\377\377\377\377\377\377\377\377\377\376\376\376\377\374\374\374\377\372" + "\372\372\377\370\370\370\377\366\366\366\377\364\364\364\377\362\362\362" + "\377\360\360\360\377\356\356\356\377\354\354\354\377\352\352\352\377\350" + "\350\350\377\347\347\347\223\0o\346Z\1m\350\377\1n\352\377\1o\354\377\1p" + "\356\377\1q\360\377\1r\362\377\1s\364\377\1t\366\377\1u\370\377\1v\372\377" + "\1w\374\377\1w\375\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1\231\377\377\1\217\377\377\1x\377\377\40" + "\210\377\377\242\333\377\377\374\376\377\377\377\377\377\377\377\377\377" + "\377\375\375\375\377\374\374\374\377\372\372\372\377\370\370\370\377\366" + "\366\366\377\364\364\364\377\362\362\362\377\360\360\360\377\356\356\356" + "\377\354\354\354\377\352\352\352\377\350\350\350\377\352\352\352_\0r\355" + "\35\1m\347\376\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\361\377\1r" + "\363\377\1s\365\377\1t\367\377\1u\371\377\1v\373\377\1w\374\377\1x\376\377" + "\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "\230\377\377\1\216\377\377\1x\377\377\1x\377\377\21\200\377\377\317\346\377" + "\377\377\377\377\377\376\376\376\377\374\374\374\377\373\373\373\377\371" + "\371\371\377\367\367\367\377\365\365\365\377\363\363\363\377\361\361\361" + "\377\357\357\357\377\355\355\355\377\353\353\353\377\351\351\351\377\347" + "\347\347\375\350\350\350\26\0\0\0\0\1l\347\306\1n\351\377\1o\353\377\1o\354" + "\377\1p\356\377\1q\360\377\1r\362\377\1s\364\377\1t\366\377\1u\370\377\1" + "v\372\377\1v\373\377\1w\375\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377" + "\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1\232\377\377\1\214\377\377\1x\377\377\1x\377" + "\377\1x\377\377\35\207\377\377\351\363\377\377\375\375\375\377\373\373\373" + "\377\372\372\372\377\370\370\370\377\366\366\366\377\364\364\364\377\362" + "\362\362\377\360\360\360\377\356\356\356\377\354\354\354\377\353\353\353" + "\377\351\351\351\377\351\351\351\317\0\0\0\0\0\0\0\0\0n\347k\1m\350\377\1" + "n\352\377\1o\354\377\1p\356\377\1p\357\377\1q\361\377\1r\363\377\1s\365\377" + "\1t\367\377\1u\370\377\1v\372\377\1w\374\377\1w\375\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1x\377\377\1\232\377\377\1\212\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1x\377\377M\240\375\377\374\374\374\377\372" + "\372\372\377\370\370\370\377\367\367\367\377\365\365\365\377\363\363\363" + "\377\361\361\361\377\357\357\357\377\356\356\356\377\354\354\354\377\352" + "\352\352\377\350\350\350\377\351\351\351r\0\0\0\0\0\0\0\0\0k\344\23\1m\347" + "\365\1n\351\377\1o\353\377\1p\355\377\1p\357\377\1q\360\377\1r\362\377\1" + "s\364\377\1t\366\377\1t\367\377\1u\371\377\1v\372\377\1w\374\377\1w\375\377" + "\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1\235\377\377\1\212\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1w\375\377\1w\374\377\257\322\372\377" + "\371\371\371\377\367\367\367\377\366\366\366\377\364\364\364\377\362\362" + "\362\377\360\360\360\377\357\357\357\377\355\355\355\377\353\353\353\377" + "\351\351\351\377\347\347\347\366\350\350\350\26\0\0\0\0\0\0\0\0\0\0\0\0\2" + "l\346\216\1m\350\377\1n\352\377\1o\354\377\1p\355\377\1p\357\377\1q\361\377" + "\1r\363\377\1s\364\377\1t\366\377\1u\370\377\1u\371\377\1v\372\377\1w\374" + "\377\1w\375\377\1x\376\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1" + "x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1\233\377\377\1\215" + "\377\377\1x\377\377\1x\376\377\1w\375\377\1w\374\377\1v\372\3774\221\371" + "\377\370\370\370\377\366\366\366\377\364\364\364\377\363\363\363\377\361" + "\361\361\377\357\357\357\377\355\355\355\377\354\354\354\377\352\352\352" + "\377\350\350\350\377\351\351\351\226\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0a\333" + "\25\1m\347\361\1n\351\377\1o\353\377\1o\354\377\1p\356\377\1q\360\377\1q" + "\361\377\1r\363\377\1s\365\377\1t\366\377\1u\370\377\1u\371\377\1v\372\377" + "\1v\373\377\4y\374\377N\240\375\377\203\275\376\377l\261\377\377\32\205\377" + "\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1x\377\377\1\225\377\377" + "\1\221\376\377\1w\375\377\1w\374\377\1v\373\377\1v\372\377\1u\371\377\1u" + "\370\377\314\340\366\377\365\365\365\377\363\363\363\377\361\361\361\377" + "\360\360\360\377\356\356\356\377\354\354\354\377\353\353\353\377\351\351" + "\351\377\347\347\347\361\351\351\351\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0n\351\200\1m\350\377\1n\351\377\1o\353\377\1p\355\377\1p\357\377" + "\1q\360\377\1r\362\377\1r\363\377\1s\365\377\1t\366\377\1t\367\377\1u\370" + "\377\15|\372\377\303\335\373\377\374\374\374\377\374\374\374\377\375\375" + "\375\377\360\366\375\377N\240\376\377\1x\376\377\1x\376\377\1x\376\377\1" + "w\375\377\1\211\375\377\1\231\374\377\1w\374\377\1v\373\377\1v\372\377\1" + "u\370\377\1t\367\377\1t\366\377\207\273\365\377\363\363\363\377\362\362\362" + "\377\360\360\360\377\357\357\357\377\355\355\355\377\353\353\353\377\351" + "\351\351\377\350\350\350\377\351\351\351\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0f\314\5\1m\346\312\1m\350\377\1n\352\377\1o\354\377" + "\1p\355\377\1p\357\377\1q\360\377\1r\362\377\1r\363\377\1s\364\377\1t\366" + "\377\1t\367\377\202\272\370\377\371\371\371\377\372\372\372\377\372\372\372" + "\377\373\373\373\377\373\373\373\377\362\367\374\377\31\203\374\377\1w\374" + "\377\1w\374\377\1v\373\377\1w\373\377\1\243\372\377\1v\372\377\1u\371\377" + "\1u\370\377\1t\367\377\1t\366\377\1s\364\377\\\243\363\377\362\362\362\377" + "\360\360\360\377\357\357\357\377\355\355\355\377\354\354\354\377\352\352" + "\352\377\350\350\350\377\347\347\347\314\377\377\377\4\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0q\352$\1m\350\361\1n\351\377\1n\352" + "\377\1o\354\377\1p\355\377\1p\357\377\1q\360\377\1q\361\377\1r\363\377\1" + "s\364\377\1s\365\377\307\335\366\377\367\367\367\377\370\370\370\377\370" + "\370\370\377\371\371\371\377\371\371\371\377\372\372\372\377V\243\372\377" + "\1v\372\377\1v\372\377\1u\371\377\1u\371\377\1\237\370\377\1x\370\377\1t" + "\367\377\1t\366\377\1s\365\377\1s\364\377\1r\363\377N\232\361\377\360\360" + "\360\377\357\357\357\377\355\355\355\377\354\354\354\377\352\352\352\377" + "\351\351\351\377\350\350\350\363\356\356\356,\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0o\347U\1m\347\374\1n\351\377" + "\1n\352\377\1o\354\377\1p\355\377\1p\357\377\1q\360\377\1q\361\377\1r\362" + "\377\1r\363\377\271\324\364\377\365\365\365\377\366\366\366\377\366\366\366" + "\377\367\367\367\377\367\367\367\377\370\370\370\377L\235\370\377\1u\370" + "\377\1u\370\377\1t\367\377\1t\367\377\1\231\366\377\1z\366\377\1s\365\377" + "\1s\364\377\1r\363\377\1r\362\377\1q\361\377W\236\360\377\357\357\357\377" + "\355\355\355\377\354\354\354\377\352\352\352\377\351\351\351\377\347\347" + "\347\376\352\352\352W\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0l\347j\1m\347\376\1n\351\377\1n\352" + "\377\1o\354\377\1p\355\377\1p\356\377\1p\357\377\1q\360\377\1q\361\377Y\240" + "\362\377\363\363\363\377\364\364\364\377\364\364\364\377\365\365\365\377" + "\365\365\365\377\334\350\365\377\15z\366\377\1t\366\377\1s\365\377\1s\365" + "\377\1s\365\377\1\230\364\377\1z\364\377\1r\363\377\1r\362\377\1q\361\377" + "\1q\360\377\1p\357\377|\261\356\377\355\355\355\377\354\354\354\377\352\352" + "\352\377\351\351\351\377\347\347\347\375\346\346\346g\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0o\353s\1m\347\375\1n\351\377\1n\352\377\1o\353\377\1o\354\377" + "\1p\355\377\1p\357\377\1p\357\377\1q\360\377p\254\361\377\356\360\362\377" + "\362\362\362\377\363\363\363\377\326\344\363\3775\216\363\377\1s\364\377" + "\1s\364\377\1r\363\377\1r\363\377\1r\363\377\1\222\362\377\1x\362\377\1q" + "\361\377\1q\360\377\1p\357\377\1p\357\377\1p\355\377\303\327\354\377\353" + "\353\353\377\352\352\352\377\351\351\351\377\350\350\350\375\353\353\353" + "s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0m\347T\1m\347\364\1m\350" + "\377\1n\351\377\1o\353\377\1o\354\377\1p\355\377\1p\356\377\1p\356\377\1" + "p\357\377\24{\360\377N\231\360\377B\224\361\377\10u\361\377\1q\361\377\1" + "q\361\377\1q\361\377\1q\361\377\1q\361\377\1q\361\377\1\221\360\377\1x\360" + "\377\1p\357\377\1p\356\377\1p\356\377\1p\355\377D\222\354\377\353\353\353" + "\377\351\351\351\377\350\350\350\377\347\347\347\366\352\352\352W\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0p\3520\1n\350\317" + "\1m\350\377\1n\351\377\1n\352\377\1o\353\377\1o\354\377\1o\354\377\1p\355" + "\377\1p\356\377\1p\356\377\1p\357\377\1p\357\377\1p\357\377\1p\357\377\1" + "p\357\377\1p\357\377\1p\357\377\1p\357\377\1\227\356\377\1y\356\377\1p\355" + "\377\1o\354\377\1o\354\377\21w\353\377\314\332\352\377\351\351\351\377\350" + "\350\350\377\350\350\350\321\356\356\356,\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0U\377\3\0n\351t\1m\347" + "\362\1m\350\377\1n\351\377\1n\352\377\1o\353\377\1o\353\377\1o\354\377\1" + "o\354\377\1p\355\377\1p\355\377\1p\355\377\1p\355\377\1p\355\377\1p\355\377" + "\1p\355\377\1p\355\377\1q\354\377\1o\354\377\1o\353\377\1o\353\377\14t\352" + "\377\260\313\351\377\350\350\350\377\350\350\350\360\354\354\354w\377\377" + "\377\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0o\346\36\2m\350\235\1m\347\367\1" + "m\350\377\1n\351\377\1n\351\377\1n\352\377\1n\352\377\1o\353\377\1o\353\377" + "\1o\353\377\1o\353\377\1o\353\377\1o\353\377\1o\353\377\1o\353\377\1n\352" + "\377\1n\352\377\1n\351\377-\204\351\377\277\322\350\377\347\347\347\365\350" + "\350\350\231\350\350\350\26\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0h\350\26\0n\351t\1m\347\314\1m\347\374\1m\350\377\1m" + "\350\377\1n\351\377\1n\351\377\1n\351\377\1n\351\377\1n\351\377\1n\351\377" + "\1n\351\377\1n\351\377\1m\350\377'\201\350\377\206\263\347\375\341\344\347" + "\303\347\347\347j\343\343\343\22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f\335\17" + "\0j\345M\2m\345\210\1m\347\276\1m\347\343\12r\350\371\20u\351\376\24x\351" + "\375)\204\351\374D\221\351\365i\245\352\335\235\302\351\242\344\344\347U" + "\351\351\351\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0", +}; + +struct sdlappicon sdlappicon = { + 48,48, + sdlappicon_pixels +}; diff --git a/polymer/eduke32/source/sw/rsrc/game_icon.ico b/polymer/eduke32/source/sw/rsrc/game_icon.ico new file mode 100644 index 000000000..fafdfaa58 Binary files /dev/null and b/polymer/eduke32/source/sw/rsrc/game_icon.ico differ diff --git a/polymer/eduke32/source/sw/rsrc/game_icon.png b/polymer/eduke32/source/sw/rsrc/game_icon.png new file mode 100644 index 000000000..4ac332ddc Binary files /dev/null and b/polymer/eduke32/source/sw/rsrc/game_icon.png differ diff --git a/polymer/eduke32/source/sw/rsrc/game_icon.svg b/polymer/eduke32/source/sw/rsrc/game_icon.svg new file mode 100644 index 000000000..29fa072e4 --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/game_icon.svg @@ -0,0 +1,134 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/polymer/eduke32/source/sw/rsrc/gameres.rc b/polymer/eduke32/source/sw/rsrc/gameres.rc new file mode 100644 index 000000000..c89e0a38c --- /dev/null +++ b/polymer/eduke32/source/sw/rsrc/gameres.rc @@ -0,0 +1,53 @@ +#include +#include +#include "startwin.game.h" + +RSRC_ICON ICON "game_icon.ico" +RSRC_BMP BITMAP "game.bmp" + +WIN_STARTWIN DIALOGEX DISCARDABLE 20, 40, 260, 200 +STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE | WS_SYSMENU +CAPTION "Startup" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", WIN_STARTWIN_BITMAP, "STATIC", SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 32, 32 + CONTROL "", WIN_STARTWIN_TABCTL, WC_TABCONTROL, WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 5, 250, 170 + CONTROL "&Start", WIN_STARTWIN_START, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 180, 48, 14 + CONTROL "&Cancel", WIN_STARTWIN_CANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 207, 180, 48, 14 + + CONTROL "", WIN_STARTWIN_MESSAGES, "EDIT", ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VSCROLL, 0, 0, 32, 32 +END + +WIN_STARTWINPAGE_CONFIG DIALOGEX DISCARDABLE 20, 40, 279, 168 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +CAPTION "Dialog" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "&Video mode:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 8, 50, 8 + CONTROL "", IDCVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 6, 80, 56 + CONTROL "&Fullscreen", IDCFULLSCREEN, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 148, 8, 49, 10 + + CONTROL "S&ound quality:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 24, 50, 8 + CONTROL "", IDCSOUNDQUAL, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 22, 110, 72 + + CONTROL "Input devices:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 50, 50, 8 + CONTROL "Mo&use", IDCINPUTMOUSE, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 60, 50, 49, 8 + CONTROL "&Joystick", IDCINPUTJOY, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 110, 50, 49, 8 + + CONTROL "&Always show configuration on start", IDCALWAYSSHOW, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 118, 116, 140, 8 +END + +WIN_STARTWINPAGE_GAME DIALOGEX DISCARDABLE 20, 40, 279, 168 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +CAPTION "Dialog" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "&Game or addon:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 5, 100, 8 + CONTROL "", IDGDATA, "LISTBOX", LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS | LBS_SORT | WS_CHILD | WS_BORDER | WS_VISIBLE | WS_TABSTOP, 10, 15, 226, 50 +END + +#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) +1 24 "64/manifest.game.xml" +#else +1 24 "32/manifest.game.xml" +#endif diff --git a/polymer/eduke32/source/sw/src/GameListSource.game.h b/polymer/eduke32/source/sw/src/GameListSource.game.h new file mode 100644 index 000000000..1588dd5c0 --- /dev/null +++ b/polymer/eduke32/source/sw/src/GameListSource.game.h @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------- +/* + Copyright (C) 2013 Jonathon Fowler + + This file is part of JFShadowWarrior + + Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//------------------------------------------------------------------------- + +@interface GameListSource : NSObject +{ + NSMutableArray *list; +} +- (id)init; +- (void)dealloc; +- (GrpFile *)grpAtIndex:(int)index; +- (int)findIndexForGrpname:(NSString *)grpname; +- (id)tableView:(NSTableView *)aTableView + objectValueForTableColumn:(NSTableColumn *)aTableColumn + row:(NSInteger)rowIndex; +- (int)numberOfRowsInTableView:(NSTableView *)aTableView; +@end + diff --git a/polymer/eduke32/source/sw/src/GameListSource.game.m b/polymer/eduke32/source/sw/src/GameListSource.game.m new file mode 100644 index 000000000..93e67e734 --- /dev/null +++ b/polymer/eduke32/source/sw/src/GameListSource.game.m @@ -0,0 +1,89 @@ +//------------------------------------------------------------------------- +/* + Copyright (C) 2013 Jonathon Fowler + + This file is part of JFShadowWarrior + + Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//------------------------------------------------------------------------- + + +#import + +#import "GrpFile.game.h" +#import "GameListSource.game.h" + +@implementation GameListSource +- (id)init +{ + self = [super init]; + if (self) { + struct grpfile *p; + int i; + + list = [[NSMutableArray alloc] init]; + + for (p = foundgrps; p; p=p->next) { + for (i=0; icrcval == grpfiles[i].crcval) break; + if (i == numgrpfiles) continue; + [list addObject:[[GrpFile alloc] initWithGrpfile:p andName:[NSString stringWithUTF8String:grpfiles[i].name]]]; + } + } + + return self; +} + +- (void)dealloc +{ + [list release]; + [super dealloc]; +} + +- (GrpFile*)grpAtIndex:(int)index +{ + return [list objectAtIndex:index]; +} + +- (int)findIndexForGrpname:(NSString*)grpname +{ + unsigned i; + for (i=0; i<[list count]; i++) { + if ([[[list objectAtIndex:i] grpname] isEqual:grpname]) return i; + } + return -1; +} + +- (id)tableView:(NSTableView *)aTableView + objectValueForTableColumn:(NSTableColumn *)aTableColumn + row:(NSInteger)rowIndex +{ + NSParameterAssert(rowIndex >= 0 && rowIndex < [list count]); + switch ([[aTableColumn identifier] intValue]) { + case 0: // name column + return [[list objectAtIndex:rowIndex] name]; + case 1: // grp column + return [[list objectAtIndex:rowIndex] grpname]; + default: return nil; + } +} + +- (int)numberOfRowsInTableView:(NSTableView *)aTableView +{ + return [list count]; +} +@end + diff --git a/polymer/eduke32/source/sw/src/GrpFile.game.h b/polymer/eduke32/source/sw/src/GrpFile.game.h new file mode 100644 index 000000000..b81d28799 --- /dev/null +++ b/polymer/eduke32/source/sw/src/GrpFile.game.h @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------- +/* + Copyright (C) 2013 Jonathon Fowler + + This file is part of JFShadowWarrior + + Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//------------------------------------------------------------------------- + + +#import + +#include "grpscan.h" + +@interface GrpFile : NSObject +{ + NSString *name; + struct grpfile *fg; +} +- (id)initWithGrpfile:(struct grpfile *)grpfile andName:(NSString *)aName; +- (void)dealloc; +- (NSString *)name; +- (NSString *)grpname; +- (struct grpfile *)entryptr; +@end + diff --git a/polymer/eduke32/source/sw/src/GrpFile.game.m b/polymer/eduke32/source/sw/src/GrpFile.game.m new file mode 100644 index 000000000..79f73b0b8 --- /dev/null +++ b/polymer/eduke32/source/sw/src/GrpFile.game.m @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------- +/* + Copyright (C) 2013 Jonathon Fowler + + This file is part of JFShadowWarrior + + Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//------------------------------------------------------------------------- + +#include "GrpFile.game.h" + +@implementation GrpFile +- (id)initWithGrpfile:(struct grpfile *)grpfile andName:(NSString*)aName +{ + self = [super init]; + if (self) { + fg = grpfile; + name = aName; + [aName retain]; + } + return self; +} +- (void)dealloc +{ + [name release]; + [super dealloc]; +} +- (NSString *)name +{ + return name; +} +- (NSString *)grpname +{ + return [NSString stringWithUTF8String:(fg->name)]; +} +- (struct grpfile *)entryptr +{ + return fg; +} +@end diff --git a/polymer/eduke32/source/sw/src/StartupWinController.game.m b/polymer/eduke32/source/sw/src/StartupWinController.game.m new file mode 100644 index 000000000..571199803 --- /dev/null +++ b/polymer/eduke32/source/sw/src/StartupWinController.game.m @@ -0,0 +1,463 @@ +//------------------------------------------------------------------------- +/* + Copyright (C) 2007 Jonathon Fowler + + This file is part of JFShadowWarrior + + Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//------------------------------------------------------------------------- + +#import + +#include "compat.h" +#include "types.h" +#include "build.h" +#include "baselayer.h" +#include "grpscan.h" +#include "gamedefs.h" +#include "config.h" + +#import "GrpFile.game.h" +#import "GameListSource.game.h" + +static struct { + int fullscreen; + int xdim3d, ydim3d, bpp3d; + int forcesetup; + char selectedgrp[BMAX_PATH+1]; + int samplerate, bitspersample, channels; + int usemouse, usejoystick; +} settings; + +static struct soundQuality_t { + int frequency; + int samplesize; + int channels; +} * soundQualities = 0; + + +@interface StartupWinController : NSWindowController +{ + NSMutableArray *modeslist3d; + GameListSource *gamelistsrc; + + IBOutlet NSButton *alwaysShowButton; + IBOutlet NSButton *fullscreenButton; + IBOutlet NSButton *useMouseButton; + IBOutlet NSButton *useJoystickButton; + IBOutlet NSTextView *messagesView; + IBOutlet NSTabView *tabView; + IBOutlet NSPopUpButton *videoMode3DPUButton; + IBOutlet NSPopUpButton *soundQualityPUButton; + IBOutlet NSScrollView *gameList; + + IBOutlet NSButton *cancelButton; + IBOutlet NSButton *startButton; +} + +- (void)dealloc; +- (void)populateVideoModes:(BOOL)firstTime; +- (void)populateSoundQuality:(BOOL)firstTime; + +- (IBAction)alwaysShowClicked:(id)sender; +- (IBAction)fullscreenClicked:(id)sender; + +- (IBAction)cancel:(id)sender; +- (IBAction)start:(id)sender; + +- (void)setupRunMode; +- (void)setupMessagesMode; +- (void)putsMessage:(NSString *)str; +- (void)setTitle:(NSString *)str; +@end + +@implementation StartupWinController + +- (void)dealloc +{ + [gamelistsrc release]; + [modeslist3d release]; + [super dealloc]; +} + +- (void)populateVideoModes:(BOOL)firstTime +{ + int i, mode3d, fullscreen = ([fullscreenButton state] == NSOnState); + int idx3d = -1; + int xdim, ydim, bpp; + + if (firstTime) { + xdim = settings.xdim3d; + ydim = settings.ydim3d; + bpp = settings.bpp3d; + } else { + mode3d = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue]; + if (mode3d >= 0) { + xdim = validmode[mode3d].xdim; + ydim = validmode[mode3d].ydim; + bpp = validmode[mode3d].bpp; + } + + } + mode3d = checkvideomode(&xdim, &ydim, bpp, fullscreen, 1); + if (mode3d < 0) { + int i, cd[] = { 32, 24, 16, 15, 8, 0 }; + for (i=0; cd[i]; ) { if (cd[i] >= bpp) i++; else break; } + for ( ; cd[i]; i++) { + mode3d = checkvideomode(&xdim, &ydim, cd[i], fullscreen, 1); + if (mode3d < 0) continue; + break; + } + } + + [modeslist3d release]; + [videoMode3DPUButton removeAllItems]; + + modeslist3d = [[NSMutableArray alloc] init]; + + for (i = 0; i < validmodecnt; i++) { + if (fullscreen == validmode[i].fs) { + if (i == mode3d) idx3d = [modeslist3d count]; + [modeslist3d addObject:[NSNumber numberWithInt:i]]; + [videoMode3DPUButton addItemWithTitle:[NSString stringWithFormat:@"%d %C %d %d-bpp", + validmode[i].xdim, 0xd7, validmode[i].ydim, validmode[i].bpp]]; + } + } + + if (idx3d >= 0) [videoMode3DPUButton selectItemAtIndex:idx3d]; +} + +- (void)populateSoundQuality:(BOOL)firstTime +{ + int i, curidx = -1; + + [soundQualityPUButton removeAllItems]; + + for (i = 0; soundQualities[i].frequency > 0; i++) { + const char *ch; + switch (soundQualities[i].channels) { + case 1: ch = "Mono"; break; + case 2: ch = "Stereo"; break; + default: ch = "?"; break; + } + + NSString *s = [NSString stringWithFormat:@"%dkHz, %d-bit, %s", + soundQualities[i].frequency / 1000, + soundQualities[i].samplesize, + ch + ]; + [soundQualityPUButton addItemWithTitle:s]; + + if (firstTime && + soundQualities[i].frequency == settings.samplerate && + soundQualities[i].samplesize == settings.bitspersample && + soundQualities[i].channels == settings.channels) { + curidx = i; + } + } + + if (firstTime && curidx < 0) { + soundQualities[i].frequency = settings.samplerate; + soundQualities[i].samplesize = settings.bitspersample; + soundQualities[i].channels = settings.channels; + + const char *ch; + switch (soundQualities[i].channels) { + case 1: ch = "Mono"; break; + case 2: ch = "Stereo"; break; + default: ch = "?"; break; + } + NSString *s = [NSString stringWithFormat:@"%dkHz, %d-bit, %s", + soundQualities[i].frequency / 1000, + soundQualities[i].samplesize, + ch + ]; + [soundQualityPUButton addItemWithTitle:s]; + + curidx = i++; + soundQualities[i].frequency = -1; + } + + if (curidx >= 0) { + [soundQualityPUButton selectItemAtIndex:curidx]; + } +} + +- (IBAction)alwaysShowClicked:(id)sender +{ +} + +- (IBAction)fullscreenClicked:(id)sender +{ + [self populateVideoModes:NO]; +} + +- (IBAction)cancel:(id)sender +{ + [NSApp abortModal]; +} + +- (IBAction)start:(id)sender +{ + int mode = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue]; + if (mode >= 0) { + settings.xdim3d = validmode[mode].xdim; + settings.ydim3d = validmode[mode].ydim; + settings.bpp3d = validmode[mode].bpp; + settings.fullscreen = validmode[mode].fs; + } + + int quality = [soundQualityPUButton indexOfSelectedItem]; + if (quality >= 0) { + settings.samplerate = soundQualities[quality].frequency; + settings.bitspersample = soundQualities[quality].samplesize; + settings.channels = soundQualities[quality].channels; + } + + int row = [[gameList documentView] selectedRow]; + if (row >= 0) { + struct grpfile *p = [[gamelistsrc grpAtIndex:row] entryptr]; + if (p) { + strcpy(settings.selectedgrp, p->name); + } + } + + settings.usemouse = [useMouseButton state] == NSOnState; + settings.usejoystick = [useJoystickButton state] == NSOnState; + settings.forcesetup = [alwaysShowButton state] == NSOnState; + + [NSApp stopModal]; +} + +- (void)setupRunMode +{ + getvalidmodes(); + + [fullscreenButton setState: (settings.fullscreen ? NSOnState : NSOffState)]; + [alwaysShowButton setState: (settings.forcesetup ? NSOnState : NSOffState)]; + [useMouseButton setState: (settings.usemouse ? NSOnState : NSOffState)]; + [useJoystickButton setState: (settings.usejoystick ? NSOnState : NSOffState)]; + [self populateVideoModes:YES]; + [self populateSoundQuality:YES]; + + // enable all the controls on the Configuration page + NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator]; + NSControl *control; + while ((control = [enumerator nextObject])) { + [control setEnabled:true]; + } + + gamelistsrc = [[GameListSource alloc] init]; + [[gameList documentView] setDataSource:gamelistsrc]; + [[gameList documentView] deselectAll:nil]; + + int row = [gamelistsrc findIndexForGrpname:[NSString stringWithUTF8String:settings.selectedgrp]]; + if (row >= 0) { + [[gameList documentView] scrollRowToVisible:row]; + [[gameList documentView] selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; + } + + [cancelButton setEnabled:true]; + [startButton setEnabled:true]; + + [tabView selectTabViewItemAtIndex:0]; + [NSCursor unhide]; // Why should I need to do this? +} + +- (void)setupMessagesMode +{ + [tabView selectTabViewItemAtIndex:2]; + + // disable all the controls on the Configuration page except "always show", so the + // user can enable it if they want to while waiting for something else to happen + NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator]; + NSControl *control; + while ((control = [enumerator nextObject])) { + if (control == alwaysShowButton) continue; + [control setEnabled:false]; + } + + [cancelButton setEnabled:false]; + [startButton setEnabled:false]; +} + +- (void)putsMessage:(NSString *)str +{ + NSRange end; + NSTextStorage *text = [messagesView textStorage]; + BOOL shouldAutoScroll; + + shouldAutoScroll = ((int)NSMaxY([messagesView bounds]) == (int)NSMaxY([messagesView visibleRect])); + + end.location = [text length]; + end.length = 0; + + [text beginEditing]; + [messagesView replaceCharactersInRange:end withString:str]; + [text endEditing]; + + if (shouldAutoScroll) { + end.location = [text length]; + end.length = 0; + [messagesView scrollRangeToVisible:end]; + } +} + +- (void)setTitle:(NSString *)str +{ + [[self window] setTitle:str]; +} + +@end + +static StartupWinController *startwin = nil; + +int startwin_open(void) +{ + if (startwin != nil) return 1; + + startwin = [[StartupWinController alloc] initWithWindowNibName:@"startwin.game"]; + if (startwin == nil) return -1; + + { + static unsigned soundQualityFrequencies[] = { 44100, 22050, 11025 }; + static unsigned soundQualitySampleSizes[] = { 16, 8 }; + static unsigned soundQualityChannels[] = { 2, 1 }; + unsigned f, b, c, i; + + i = sizeof(soundQualityFrequencies) * + sizeof(soundQualitySampleSizes) * + sizeof(soundQualityChannels) / + sizeof(int) + 2; // one for the terminator, one for a custom setting + soundQualities = (struct soundQuality_t *) malloc(i * sizeof(struct soundQuality_t)); + + i = 0; + for (c = 0; c < sizeof(soundQualityChannels) / sizeof(int); c++) { + for (b = 0; b < sizeof(soundQualitySampleSizes) / sizeof(int); b++) { + for (f = 0; f < sizeof(soundQualityFrequencies) / sizeof(int); f++) { + soundQualities[i].frequency = soundQualityFrequencies[f]; + soundQualities[i].samplesize = soundQualitySampleSizes[b]; + soundQualities[i].channels = soundQualityChannels[c]; + + i++; + } + } + } + + soundQualities[i].frequency = -1; + } + + [startwin setupMessagesMode]; + [startwin showWindow:nil]; + + return 0; +} + +int startwin_close(void) +{ + if (startwin == nil) return 1; + + [startwin close]; + [startwin release]; + startwin = nil; + + return 0; +} + +int startwin_puts(const char *s) +{ + NSString *ns; + + if (!s) return -1; + if (startwin == nil) return 1; + + ns = [[NSString alloc] initWithCString:s]; + [startwin putsMessage:ns]; + [ns release]; + + return 0; +} + +int startwin_settitle(const char *s) +{ + NSString *ns; + + if (!s) return -1; + if (startwin == nil) return 1; + + ns = [[NSString alloc] initWithCString:s]; + [startwin setTitle:ns]; + [ns release]; + + return 0; +} + +int startwin_idle(void *v) +{ + if (startwin) [[startwin window] displayIfNeeded]; + return 0; +} + +extern char* grpfile; +extern int32 ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP, ForceSetup, UseMouse, UseJoystick; + +int startwin_run(void) +{ + int retval; + + if (startwin == nil) return 0; + + ScanGroups(); + + settings.fullscreen = ScreenMode; + settings.xdim3d = ScreenWidth; + settings.ydim3d = ScreenHeight; + settings.bpp3d = ScreenBPP; + settings.samplerate = MixRate; + settings.bitspersample = NumBits; + settings.channels = NumChannels; + settings.usemouse = UseMouse; + settings.usejoystick = UseJoystick; + settings.forcesetup = ForceSetup; + strncpy(settings.selectedgrp, grpfile, BMAX_PATH); + + [startwin setupRunMode]; + + switch ([NSApp runModalForWindow:[startwin window]]) { + case NSRunStoppedResponse: retval = 1; break; + case NSRunAbortedResponse: retval = 0; break; + default: retval = -1; + } + + [startwin setupMessagesMode]; + + if (retval) { + ScreenMode = settings.fullscreen; + ScreenWidth = settings.xdim3d; + ScreenHeight = settings.ydim3d; + ScreenBPP = settings.bpp3d; + MixRate = settings.samplerate; + NumBits = settings.bitspersample; + NumChannels = settings.channels; + UseMouse = settings.usemouse; + UseJoystick = settings.usejoystick; + ForceSetup = settings.forcesetup; + grpfile = settings.selectedgrp; + } + + return retval; +} diff --git a/polymer/eduke32/source/sw/src/_config.h b/polymer/eduke32/source/sw/src/_config.h new file mode 100644 index 000000000..4551f2630 --- /dev/null +++ b/polymer/eduke32/source/sw/src/_config.h @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifndef config_private_ +#define config_private_ + +//#define SETUPFILENAME "SW.CFG" + +#endif + + diff --git a/polymer/eduke32/source/sw/src/_functio.h b/polymer/eduke32/source/sw/src/_functio.h new file mode 100644 index 000000000..7dfaee607 --- /dev/null +++ b/polymer/eduke32/source/sw/src/_functio.h @@ -0,0 +1,382 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +// _functio.h + +// file created by makehead.exe +// these headers contain default key assignments, as well as +// default button assignments and game function names +// axis defaults are also included + + +#ifndef function_private_ +#define function_private_ +char *gamefunctions[] = +{ + "Move_Forward", + "Move_Backward", + "Turn_Left", + "Turn_Right", + "Strafe", + "Fire", + "Open", + "Run", + "AutoRun", + "Jump", + "Crouch", + "Look_Up", + "Look_Down", + "Strafe_Left", + "Strafe_Right", + "Aim_Up", + "Aim_Down", + "Weapon_1", + "Weapon_2", + "Weapon_3", + "Weapon_4", + "Weapon_5", + "Weapon_6", + "Weapon_7", + "Weapon_8", + "Weapon_9", + "Weapon_10", + "Inventory", + "Inventory_Left", + "Inventory_Right", + "Med_Kit", + "Smoke_Bomb", + "Night_Vision", + "Gas_Bomb", + "Flash_Bomb", + "Caltrops", + "TurnAround", + "SendMessage", + "Map", + "Shrink_Screen", + "Enlarge_Screen", + "Center_View", + "Holster_Weapon", + "Map_Follow_Mode", + "See_Co_Op_View", + "Mouse_Aiming", + "Toggle_Crosshair", + "Next_Weapon", + "Previous_Weapon", + "Show_Menu", + "Show_Console", +}; + +#define NUMKEYENTRIES 50 + +static char *keydefaults[] = +{ + "Move_Forward", "Up", "Kpad8", + "Move_Backward", "Down", "Kpad2", + "Turn_Left", "Left", "Kpad4", + "Turn_Right", "Right", "KPad6", + "Strafe", "LAlt", "RAlt", + "Fire", "LCtrl", "RCtrl", + "Open", "Space", "", + "Run", "LShift", "RShift", + "AutoRun", "CapLck", "", + "Jump", "A", "/", + "Crouch", "Z", "", + "Look_Up", "PgUp", "Kpad9", + "Look_Down", "PgDn", "Kpad3", + "Strafe_Left", ",", "", + "Strafe_Right", ".", "", + "Aim_Up", "Home", "KPad7", + "Aim_Down", "End", "Kpad1", + "Weapon_1", "1", "", + "Weapon_2", "2", "", + "Weapon_3", "3", "", + "Weapon_4", "4", "", + "Weapon_5", "5", "", + "Weapon_6", "6", "", + "Weapon_7", "7", "", + "Weapon_8", "8", "", + "Weapon_9", "9", "", + "Weapon_10", "0", "", + "Inventory", "Enter", "KpdEnt", + "Inventory_Left", "[", "", + "Inventory_Right", "]", "", + "Med_Kit", "M", "", + "Smoke_Bomb", "S", "", + "Night_Vision", "N", "", + "Gas_Bomb", "G", "", + "Flash_Bomb", "F", "", + "Caltrops", "C", "", + "TurnAround", "BakSpc", "", + "SendMessage", "T", "", + "Map", "Tab", "", + "Shrink_Screen", "-", "Kpad-", + "Enlarge_Screen", "=", "Kpad+", + "Center_View", "KPad5", "", + "Holster_Weapon", "ScrLck", "", + "Map_Follow_Mode", "F", "", + "See_Co_Op_View", "K", "", + "Mouse_Aiming", "U", "", + "Toggle_Crosshair", "I", "", + "Next_Weapon", "'", "", + "Previous_Weapon", ";", "", + "Show_Console", "NumLck", "", +}; + +static char *keydefaults_modern[] = +{ + "Move_Forward", "W", "", + "Move_Backward", "S", "", + "Turn_Left", "", "", + "Turn_Right", "", "", + "Strafe", "", "", + "Fire", "", "", + "Open", "E", "", + "Run", "LShift", "", + "AutoRun", "CapLck", "", + "Jump", "Space", "", + "Crouch", "LAlt", "", + "Look_Up", "", "", + "Look_Down", "", "", + "Strafe_Left", "A", "", + "Strafe_Right", "D", "", + "Aim_Up", "", "", + "Aim_Down", "", "", + "Weapon_1", "1", "", + "Weapon_2", "2", "", + "Weapon_3", "3", "", + "Weapon_4", "4", "", + "Weapon_5", "5", "", + "Weapon_6", "6", "", + "Weapon_7", "7", "", + "Weapon_8", "8", "", + "Weapon_9", "9", "", + "Weapon_10", "0", "", + "Inventory", "Enter", "", + "Inventory_Left", "[", "", + "Inventory_Right", "]", "", + "Med_Kit", "M", "", + "Smoke_Bomb", "B", "", + "Night_Vision", "N", "", + "Gas_Bomb", "G", "", + "Flash_Bomb", "F", "", + "Caltrops", "C", "", + "TurnAround", "BakSpc", "", + "SendMessage", "T", "", + "Map", "Tab", "", + "Shrink_Screen", "-", "", + "Enlarge_Screen", "=", "", + "Center_View", "", "", + "Holster_Weapon", "H", "", + "Map_Follow_Mode", "F", "", + "See_Co_Op_View", "K", "", + "Mouse_Aiming", "U", "", + "Toggle_Crosshair", "I", "", + "Next_Weapon", "", "", + "Previous_Weapon", "", "", + "Show_Console", "NumLck", "", +}; + + +static char *mousedefaults[] = +{ + "Fire", + "Strafe", + "Move_Forward", + "", + "" +}; + +static char *mousedefaults_modern[] = +{ + "Fire", + "Open", + "", + "", + "Next_Weapon", + "Previous_Weapon" +}; + + +static char *mouseclickeddefaults[] = +{ + "", + "Open", + "", + "", + "" +}; + +static char *mouseclickeddefaults_modern[] = +{ + "", + "", + "", + "", + "", + "" +}; + + +static char *joystickdefaults[] = +{ + "Fire", + "Strafe", + "Run", + "Open", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Aim_Down", + "Look_Right", + "Aim_Up", + "Look_Left", +}; + + +static char *joystickclickeddefaults[] = +{ + "", + "Inventory", + "Jump", + "Crouch", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +}; + + +static char *mouseanalogdefaults[] = +{ + "analog_turning", + "analog_moving", +}; + + +static char *mousedigitaldefaults[] = +{ + "", + "", + "", + "", +}; + + +static char *gamepaddigitaldefaults[] = +{ + "Turn_Left", + "Turn_Right", + "Move_Forward", + "Move_Backward", +}; + + +static char *joystickanalogdefaults[] = +{ + "analog_turning", + "analog_moving", + "analog_strafing", + "", + "", + "", + "", + "", +}; + + +static char *joystickdigitaldefaults[] = +{ + "", + "", + "", + "", + "", + "", + "Run", + "", + "", + "", + "", + "", + "", + "", + "", + "", +}; +#endif diff --git a/polymer/eduke32/source/sw/src/_rts.h b/polymer/eduke32/source/sw/src/_rts.h new file mode 100644 index 000000000..6a44becb4 --- /dev/null +++ b/polymer/eduke32/source/sw/src/_rts.h @@ -0,0 +1,79 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +/* +Copyright (C) 1996, 2003 - 3D Realms Entertainment + +This file is part of Duke Nukem 3D version 1.5 - Atomic Edition + +Duke Nukem 3D 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1996 - Todd Replogle +Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifndef rts_private__ +#define rts_private__ + +//=============== +// TYPES +//=============== + +typedef struct +{ + char name[8]; + int32 handle,position,size; +} lumpinfo_t; + +typedef struct +{ + char identification[4]; // should be IWAD + int32 numlumps; + int32 infotableofs; +} wadinfo_t; + +typedef struct +{ + int32 filepos; + int32 size; + char name[8]; +} filelump_t; + +#endif diff --git a/polymer/eduke32/source/sw/src/actor.c b/polymer/eduke32/source/sw/src/actor.c new file mode 100644 index 000000000..330f5492c --- /dev/null +++ b/polymer/eduke32/source/sw/src/actor.c @@ -0,0 +1,1019 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "tags.h" +#include "weapon.h" +#include "sprite.h" +#include "actor.h" + +extern int jump_grav; + +extern STATE s_DebrisNinja[]; +extern STATE s_DebrisRat[]; +extern STATE s_DebrisCrab[]; +extern STATE s_DebrisStarFish[]; +extern STATE s_NinjaDieSliced[]; + +extern STATEp sg_NinjaGrabThroat[]; + +int DoActorStopFall(short SpriteNum); + + +int +DoScaleSprite(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + int scale_value; + + if (u->scale_speed) + { + u->scale_value += u->scale_speed * ACTORMOVETICS; + + scale_value = u->scale_value >> 8; + + if (u->scale_speed > 0) + { + if (scale_value > u->scale_tgt) + u->scale_speed = 0; + else + sp->xrepeat = sp->yrepeat = scale_value; + } + else + { + if (scale_value < u->scale_tgt) + u->scale_speed = 0; + else + sp->xrepeat = sp->yrepeat = scale_value; + } + + } + + return 0; +} + +int +DoActorDie(short SpriteNum, short weapon) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = &sprite[SpriteNum]; + + + change_sprite_stat(SpriteNum, STAT_DEAD_ACTOR); + SET(u->Flags, SPR_DEAD); + RESET(u->Flags, SPR_FALLING | SPR_JUMPING); + u->floor_dist = Z(40); + + // test for gibable dead bodies + SET(sp->extra, SPRX_BREAKABLE); + SET(sp->cstat, CSTAT_SPRITE_BREAKABLE); + + if (weapon < 0) + { + // killed by one of these non-sprites + switch (weapon) + { + case WPN_NM_LAVA: + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + break; + + case WPN_NM_SECTOR_SQUISH: + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + break; + } + + return 0; + } + + + // killed by one of these sprites + switch (User[weapon]->ID) + { + // Coolie actually explodes himself + // he is the Sprite AND Weapon + case COOLIE_RUN_R0: + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + sp->xvel <<= 1; + u->ActorActionFunc = NULL; + sprite[SpriteNum].ang = NORM_ANGLE(sprite[SpriteNum].ang + 1024); + break; + + case NINJA_RUN_R0: + if (u->ID == NINJA_RUN_R0) // Cut in half! + { + SPRITEp wp = &sprite[weapon]; + + if (User[weapon]->WeaponNum != WPN_FIST) + { + //SpawnBlood(SpriteNum, SpriteNum, -1, -1, -1, -1); + InitPlasmaFountain(wp, sp); + InitPlasmaFountain(wp, sp); + PlaySound(DIGI_NINJAINHALF,&sp->x,&sp->y,&sp->z,v3df_none); + ChangeState(SpriteNum, &s_NinjaDieSliced[0]); + } + else + { + if (RANDOM_RANGE(1000) > 500) + { + SPRITEp wp = &sprite[weapon]; + InitPlasmaFountain(wp, sp); + } + + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + u->ActorActionFunc = NULL; + sp->xvel = 200 + RANDOM_RANGE(200); + u->jump_speed = -200 - RANDOM_RANGE(250); + DoActorBeginJump(SpriteNum); + sprite[SpriteNum].ang = sprite[weapon].ang; + } + } + else + { + // test for gibable dead bodies + if (RANDOM_RANGE(1000) > 500) + SET(sp->cstat, CSTAT_SPRITE_YFLIP); + ChangeState(SpriteNum, u->StateEnd); + sp->xvel = 0; + u->jump_speed = 0; + DoActorBeginJump(SpriteNum); + } + + u->RotNum = 0; + + u->ActorActionFunc = NULL; + //u->ActorActionFunc = NullAnimator; + sprite[SpriteNum].ang = sprite[weapon].ang; + break; + + case COOLG_RUN_R0: + case SKEL_RUN_R0: + case RIPPER_RUN_R0: + case RIPPER2_RUN_R0: + case EEL_RUN_R0: + case STAR1: + case SUMO_RUN_R0: + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + break; + + case UZI_SMOKE: + if (RANDOM_RANGE(1000) > 500) + SET(sp->cstat, CSTAT_SPRITE_YFLIP); + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + // Rippers still gotta jump or they fall off walls weird + if (u->ID == RIPPER_RUN_R0 || u->ID == RIPPER2_RUN_R0) + { + sp->xvel <<= 1; + u->jump_speed = -100 - RANDOM_RANGE(250); + DoActorBeginJump(SpriteNum); + } + else + { + sp->xvel = 0; + u->jump_speed = -10 - RANDOM_RANGE(25); + DoActorBeginJump(SpriteNum); + } + u->ActorActionFunc = NULL; + // Get angle to player + sp->ang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y) + 1024); + break; + + case UZI_SMOKE+1: // Shotgun + if (RANDOM_RANGE(1000) > 500) + SET(sp->cstat, CSTAT_SPRITE_YFLIP); + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + + // Rippers still gotta jump or they fall off walls weird + if (u->ID == RIPPER_RUN_R0 || u->ID == RIPPER2_RUN_R0) + { + sp->xvel = 75 + RANDOM_RANGE(100); + u->jump_speed = -100 - RANDOM_RANGE(150); + } + else + { + sp->xvel = 100 + RANDOM_RANGE(200); + u->jump_speed = -100 - RANDOM_RANGE(250); + } + DoActorBeginJump(SpriteNum); + u->ActorActionFunc = NULL; + // Get angle to player + sp->ang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y) + 1024); + break; + + default: + ASSERT(weapon >= 0); + switch (u->ID) + { + case SKULL_R0: + case BETTY_R0: + ChangeState(SpriteNum, u->StateEnd); + break; + + default: + if (RANDOM_RANGE(1000) > 700) + { + SPRITEp wp = &sprite[weapon]; + InitPlasmaFountain(wp, sp); + } + + if (RANDOM_RANGE(1000) > 500) + SET(sp->cstat, CSTAT_SPRITE_YFLIP); + ChangeState(SpriteNum, u->StateEnd); + u->RotNum = 0; + u->ActorActionFunc = NULL; + sp->xvel = 300 + RANDOM_RANGE(400); + u->jump_speed = -300 - RANDOM_RANGE(350); + DoActorBeginJump(SpriteNum); + sprite[SpriteNum].ang = sprite[weapon].ang; + break; + } + break; + } + + // These are too big to flip upside down + switch (u->ID) + { + case RIPPER2_RUN_R0: + case COOLIE_RUN_R0: + case SUMO_RUN_R0: + case ZILLA_RUN_R0: + RESET(sp->cstat, CSTAT_SPRITE_YFLIP); + break; + } + + u->ID = 0; + + return 0; +} + +VOID +DoDebrisCurrent(SPRITEp sp) +{ + int xvect, yvect; + int nx, ny; + int ret=0; + USERp u = User[sp - sprite]; + SECT_USERp sectu = SectUser[sp->sectnum]; + + //sp->clipdist = (256+128)>>2; + + nx = DIV4(sectu->speed) * (int) sintable[NORM_ANGLE(sectu->ang + 512)] >> 14; + ny = DIV4(sectu->speed) * (int) sintable[sectu->ang] >> 14; + + // faster than move_sprite + //move_missile(sp-sprite, nx, ny, 0, Z(2), Z(0), 0, ACTORMOVETICS); + ret = move_sprite(sp-sprite, nx, ny, 0, u->ceiling_dist, u->floor_dist, 0, ACTORMOVETICS); + + // attempt to move away from wall + if (ret) + { + short rang = RANDOM_P2(2048); + + nx = DIV4(sectu->speed) * (int) sintable[NORM_ANGLE(sectu->ang + rang + 512)] >> 14; + ny = DIV4(sectu->speed) * (int) sintable[NORM_ANGLE(sectu->ang + rang)] >> 14; + + move_sprite(sp-sprite, nx, ny, 0, u->ceiling_dist, u->floor_dist, 0, ACTORMOVETICS); + } + + sp->z = u->loz; +} + +int +DoActorSectorDamage(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + SECT_USERp sectu = SectUser[sp->sectnum]; + SECTORp sectp = §or[sp->sectnum]; + + if (u->Health <= 0) + return FALSE; + + if (sectu && sectu->damage) + { + if (TEST(sectu->flags, SECTFU_DAMAGE_ABOVE_SECTOR)) + { + if ((u->DamageTics -= synctics) < 0) + { + u->DamageTics = 60; + u->Health -= sectu->damage; + + if (u->Health <= 0) + { + UpdateSinglePlayKills(SpriteNum); + DoActorDie(SpriteNum, WPN_NM_LAVA); + return TRUE; + } + } + } + else if (SPRITEp_BOS(sp) >= sectp->floorz) + { + if ((u->DamageTics -= synctics) < 0) + { + u->DamageTics = 60; + u->Health -= sectu->damage; + + if (u->Health <= 0) + { + UpdateSinglePlayKills(SpriteNum); + DoActorDie(SpriteNum, WPN_NM_LAVA); + return TRUE; + } + } + } + } + + // note that most squishing is done in vator.c + if (u->lo_sectp && u->hi_sectp && labs(u->loz - u->hiz) < DIV2(SPRITEp_SIZE_Z(sp))) + //if (u->lo_sectp && u->hi_sectp && labs(u->loz - u->hiz) < SPRITEp_SIZE_Z(sp)) + { + u->Health = 0; + if (SpawnShrap(SpriteNum, WPN_NM_SECTOR_SQUISH)) + { + UpdateSinglePlayKills(SpriteNum); + SetSuicide(SpriteNum); + } + else + { + ASSERT(TRUE == FALSE); + //DoActorDie(SpriteNum, WPN_NM_SECTOR_SQUISH); + } + + return TRUE; + } + + return FALSE; +} + + +int +move_debris(short SpriteNum, int xchange, int ychange, int zchange) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + int nx, ny; + + u->ret = move_sprite(SpriteNum, xchange, ychange, zchange, + u->ceiling_dist, u->floor_dist, 0, ACTORMOVETICS); + + return !u->ret; +} + +// !AIC - Supposed to allow floating of DEBRIS (dead bodies, flotsam, jetsam). Or if water has +// current move with the current. + +int +DoActorDebris(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + SECTORp sectp = §or[sp->sectnum]; + int nx, ny; + + // This was move from DoActorDie so actor's can't be walked through until they are on the floor + RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + + // Don't let some actors float + switch (u->ID) + { + case HORNET_RUN_R0: + case BUNNY_RUN_R0: + KillSprite(SpriteNum); + return 0; + case ZILLA_RUN_R0: + getzsofslope(sp->sectnum, sp->x, sp->y, &u->hiz, &u->loz); + u->lo_sectp = §or[sp->sectnum]; + u->hi_sectp = §or[sp->sectnum]; + u->lo_sp = NULL; + u->hi_sp = NULL; + break; + } + + if (TEST(sectp->extra, SECTFX_SINK)) + { + if (TEST(sectp->extra, SECTFX_CURRENT)) + { + DoDebrisCurrent(sp); + } + else + { + //nx = sp->xvel * ACTORMOVETICS * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + //ny = sp->xvel * ACTORMOVETICS * (int) sintable[sp->ang] >> 14; + nx = ACTORMOVETICS * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = ACTORMOVETICS * (int) sintable[sp->ang] >> 14; + + //sp->clipdist = (256+128)>>2; + + if (!move_debris(SpriteNum, nx, ny, 0L)) + { + sp->ang = RANDOM_P2(2048); + } + } + + if (SectUser[sp->sectnum] && SectUser[sp->sectnum]->depth > 10) // JBF: added null check + { + u->WaitTics = (u->WaitTics + (ACTORMOVETICS << 3)) & 1023; + //sp->z = Z(2) + u->loz + ((Z(4) * (int) sintable[u->WaitTics]) >> 14); + sp->z = u->loz - ((Z(2) * (int) sintable[u->WaitTics]) >> 14); + } + } + else + { + sp->z = u->loz; + } + + return 0; +} + + +int +DoFireFly(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + int nx, ny; + + nx = 4 * ACTORMOVETICS * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = 4 * ACTORMOVETICS * (int) sintable[sp->ang] >> 14; + + sp->clipdist = 256>>2; + if (!move_actor(SpriteNum, nx, ny, 0L)) + { + sp->ang = NORM_ANGLE(sp->ang + 1024); + } + + u->WaitTics = (u->WaitTics + (ACTORMOVETICS << 1)) & 2047; + + sp->z = u->sz + ((Z(32) * (int) sintable[u->WaitTics]) >> 14); + return 0; +} + +int +DoGenerateSewerDebris(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum], np; + USERp u = User[SpriteNum], nu; + short n; + + static STATEp Debris[] = + { + s_DebrisNinja, + s_DebrisRat, + s_DebrisCrab, + s_DebrisStarFish + }; + + u->Tics -= ACTORMOVETICS; + + if (u->Tics <= 0) + { + u->Tics = u->WaitTics; + + n = SpawnSprite(STAT_DEAD_ACTOR, 0, Debris[RANDOM_P2(4<<8)>>8], sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 200); + np = &sprite[n]; + nu = User[n]; + + SetOwner(SpriteNum, n); + } + + return 0; +} + +// !AIC - Tries to keep actors correctly on the floor. More that a bit messy. + +VOID +KeepActorOnFloor(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + SECTORp sectp; + int depth; + + sectp = §or[sp->sectnum]; + + RESET(sp->cstat, CSTAT_SPRITE_YFLIP); // If upside down, reset it + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + return; + + if (u->lo_sectp && SectUser[u->lo_sectp - sector]) + depth = SectUser[u->lo_sectp - sector]->depth; + else + depth = 0; + + if (TEST(sectp->extra, SECTFX_SINK) && + depth > 35 && + u->ActorActionSet && u->ActorActionSet->Swim) + { + if (TEST(u->Flags, SPR_SWIMMING)) + { + if (u->Rot != u->ActorActionSet->Run && u->Rot != u->ActorActionSet->Swim && u->Rot != u->ActorActionSet->Stand) + { + // was swimming but have now stopped + RESET(u->Flags, SPR_SWIMMING); + RESET(sp->cstat, CSTAT_SPRITE_YCENTER); + u->oz = sp->z = u->loz; + return; + } + + if (u->Rot == u->ActorActionSet->Run) + { + NewStateGroup(SpriteNum, u->ActorActionSet->Swim); + } + + // are swimming + u->oz = sp->z = u->loz - Z(depth); + } + else + { + // only start swimming if you are running + if (u->Rot == u->ActorActionSet->Run || u->Rot == u->ActorActionSet->Swim) + { + NewStateGroup(SpriteNum, u->ActorActionSet->Swim); + u->oz = sp->z = u->loz - Z(depth); + SET(u->Flags, SPR_SWIMMING); + SET(sp->cstat, CSTAT_SPRITE_YCENTER); + } + else + { + RESET(u->Flags, SPR_SWIMMING); + RESET(sp->cstat, CSTAT_SPRITE_YCENTER); + u->oz = sp->z = u->loz; + } + } + + return; + } + + // NOT in a swimming situation + RESET(u->Flags, SPR_SWIMMING); + RESET(sp->cstat, CSTAT_SPRITE_YCENTER); + +#if 1 + if (TEST(u->Flags, SPR_MOVED)) + { + u->oz = sp->z = u->loz; + } + else + { + int ceilz,ceilhit,florz,florhit; + FAFgetzrangepoint(sp->x, sp->y, sp->z, sp->sectnum, + &ceilz, &ceilhit, &florz, &florhit); + + u->oz = sp->z = florz; + } +#endif + + +} + +int +DoActorBeginSlide(short SpriteNum, short ang, short vel, short dec) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + SET(u->Flags, SPR_SLIDING); + + u->slide_ang = ang; + u->slide_vel = vel; + u->slide_dec = dec; + + //DoActorSlide(SpriteNum); + + return 0; +} + +// !AIC - Sliding can occur in different directions from movement of the actor. +// Has its own set of variables + +int +DoActorSlide(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int nx, ny; + + nx = u->slide_vel * (int) sintable[NORM_ANGLE(u->slide_ang + 512)] >> 14; + ny = u->slide_vel * (int) sintable[u->slide_ang] >> 14; + + if (!move_actor(SpriteNum, nx, ny, 0L)) + { + RESET(u->Flags, SPR_SLIDING); + return FALSE; + } + + u->slide_vel -= u->slide_dec * ACTORMOVETICS; + + if (u->slide_vel < 20) + { + RESET(u->Flags, SPR_SLIDING); + } + + return TRUE; +} + +// !AIC - Actor jumping and falling + +int +DoActorBeginJump(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + SET(u->Flags, SPR_JUMPING); + RESET(u->Flags, SPR_FALLING); + + // u->jump_speed = should be set before calling + + // set up individual actor jump gravity + u->jump_grav = ACTOR_GRAVITY; + + // Change sprites state to jumping + if (u->ActorActionSet) + { + if (TEST(u->Flags, SPR_DEAD)) + NewStateGroup(SpriteNum, u->ActorActionSet->DeathJump); + else + NewStateGroup(SpriteNum, u->ActorActionSet->Jump); + } + u->StateFallOverride = NULL; + + //DO NOT CALL DoActorJump! DoActorStopFall can cause an infinite loop and + //stack overflow if it is called. + //DoActorJump(SpriteNum); + + return 0; +} + +int +DoActorJump(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + int jump_adj; + + // precalculate jump value to adjust jump speed by + jump_adj = u->jump_grav * ACTORMOVETICS; + + // adjust jump speed by gravity - if jump speed greater than 0 player + // have started falling + if ((u->jump_speed += jump_adj) > 0) + { + //DSPRINTF(ds,"Actor Jump Height %d", labs(sp->z - sector[sp->sectnum].floorz)>>8 ); + MONO_PRINT(ds); + + // Start falling + DoActorBeginFall(SpriteNum); + return 0; + } + + // adjust height by jump speed + sp->z += u->jump_speed * ACTORMOVETICS; + + // if player gets to close the ceiling while jumping + if (sp->z < u->hiz + Z(PIC_SIZY(SpriteNum))) + { + // put player at the ceiling + sp->z = u->hiz + Z(PIC_SIZY(SpriteNum)); + + // reverse your speed to falling + u->jump_speed = -u->jump_speed; + + //DSPRINTF(ds,"Jump: sp_num %d, hi_num %d, hi_sect %d",SpriteNum, u->hi_sp - sprite, u->hi_sectp - sector); + MONO_PRINT(ds); + + // Change sprites state to falling + DoActorBeginFall(SpriteNum); + } + + return 0; +} + + +int +DoActorBeginFall(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + SET(u->Flags, SPR_FALLING); + RESET(u->Flags, SPR_JUMPING); + + u->jump_grav = ACTOR_GRAVITY; + + // Change sprites state to falling + if (u->ActorActionSet) + { + if (TEST(u->Flags, SPR_DEAD)) + { + NewStateGroup(SpriteNum, u->ActorActionSet->DeathFall); + } + else + NewStateGroup(SpriteNum, u->ActorActionSet->Fall); + + if (u->StateFallOverride) + { + NewStateGroup(SpriteNum, u->StateFallOverride); + } + } + + DoActorFall(SpriteNum); + + return 0; +} + + +int +DoActorFall(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // adjust jump speed by gravity + u->jump_speed += u->jump_grav * ACTORMOVETICS; + + // adjust player height by jump speed + sp->z += u->jump_speed * ACTORMOVETICS; + + // Stick like glue when you hit the ground + if (sp->z > u->loz) + { + DoActorStopFall(SpriteNum); + } + + return 0; +} + +int +DoActorStopFall(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + sp->z = u->loz; + + RESET(u->Flags, SPR_FALLING | SPR_JUMPING); + RESET(sp->cstat, CSTAT_SPRITE_YFLIP); + + + // don't stand on face or wall sprites - jump again + if (u->lo_sp && !TEST(u->lo_sp->cstat, CSTAT_SPRITE_FLOOR)) + { + USERp tu = User[u->lo_sp - sprite]; + + //sp->ang = NORM_ANGLE(sp->ang + (RANDOM_P2(64<<8)>>8) - 32); + sp->ang = NORM_ANGLE(sp->ang + 1024 + (RANDOM_P2(512<<8)>>8)); + u->jump_speed = -350; + + //DSPRINTF(ds,"StopFall: sp_num %d, sp->picnum %d, lo_num %d, lo_sp->picnum %d",SpriteNum, sp->picnum, u->lo_sp - sprite, u->lo_sp->picnum); + MONO_PRINT(ds); + + DoActorBeginJump(SpriteNum); + return 0; + } + + // Change sprites state to running + if (u->ActorActionSet) + { + if (TEST(u->Flags, SPR_DEAD)) + { + NewStateGroup(SpriteNum, u->ActorActionSet->Dead); + PlaySound(DIGI_ACTORBODYFALL1,&sp->x,&sp->y,&sp->z,v3df_none); + } + else + { + PlaySound(DIGI_ACTORHITGROUND,&sp->x,&sp->y,&sp->z,v3df_none); + + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + if ((u->track >= 0) && (u->jump_speed) > 800 && (u->ActorActionSet->Sit)) + { + u->WaitTics = 80; + NewStateGroup(SpriteNum, u->ActorActionSet->Sit); + } + } + } + + return 0; +} + +int +DoActorDeathMove(short SpriteNum) +{ + ANIMATOR DoFindGround; + + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int nx, ny; + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + if (TEST(u->Flags, SPR_JUMPING)) + DoActorJump(SpriteNum); + else + DoActorFall(SpriteNum); + } + + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + sp->clipdist = (128+64)>>2; + move_actor(SpriteNum, nx, ny, 0); + + // only fall on top of floor sprite or sector + DoFindGroundPoint(SpriteNum); + + return 0; +} + +// !AIC - Jumping a falling for shrapnel and other stuff, not actors. + +int +DoBeginJump(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + SET(u->Flags, SPR_JUMPING); + RESET(u->Flags, SPR_FALLING); + + // set up individual actor jump gravity + u->jump_grav = ACTOR_GRAVITY; + + DoJump(SpriteNum); + + return 0; +} + +int +DoJump(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + int jump_adj; + + // precalculate jump value to adjust jump speed by + jump_adj = u->jump_grav * ACTORMOVETICS; + + // adjust jump speed by gravity - if jump speed greater than 0 player + // have started falling + if ((u->jump_speed += jump_adj) > 0) + { + // Start falling + DoBeginFall(SpriteNum); + return 0; + } + + // adjust height by jump speed + sp->z += u->jump_speed * ACTORMOVETICS; + + // if player gets to close the ceiling while jumping + if (sp->z < u->hiz + Z(PIC_SIZY(SpriteNum))) + { + // put player at the ceiling + sp->z = u->hiz + Z(PIC_SIZY(SpriteNum)); + + // reverse your speed to falling + u->jump_speed = -u->jump_speed; + + // Change sprites state to falling + DoBeginFall(SpriteNum); + } + + return 0; +} + + +int +DoBeginFall(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + SET(u->Flags, SPR_FALLING); + RESET(u->Flags, SPR_JUMPING); + + u->jump_grav = ACTOR_GRAVITY; + + DoFall(SpriteNum); + + return 0; +} + +#if 0 +int +DoFall(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // adjust jump speed by gravity + u->jump_speed += u->jump_grav * ACTORMOVETICS; + + // adjust player height by jump speed + sp->z += u->jump_speed * ACTORMOVETICS; + + // Stick like glue when you hit the ground + if (sp->z > u->loz) + { + sp->z = u->loz; + RESET(u->Flags, SPR_FALLING); + } + + return 0; +} +#else +int +DoFall(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // adjust jump speed by gravity + u->jump_speed += u->jump_grav * ACTORMOVETICS; + + // adjust player height by jump speed + sp->z += u->jump_speed * ACTORMOVETICS; + + // Stick like glue when you hit the ground + if (sp->z > u->loz - u->floor_dist) + { + sp->z = u->loz - u->floor_dist; + RESET(u->Flags, SPR_FALLING); + } + + return 0; +} +#endif + + +#include "saveable.h" + +static saveable_code saveable_actor_code[] = +{ + SAVE_CODE(DoScaleSprite), + SAVE_CODE(DoActorDie), + SAVE_CODE(DoDebrisCurrent), + SAVE_CODE(DoActorSectorDamage), + SAVE_CODE(DoActorDebris), + SAVE_CODE(DoFireFly), + SAVE_CODE(DoGenerateSewerDebris), + SAVE_CODE(KeepActorOnFloor), + SAVE_CODE(DoActorBeginSlide), + SAVE_CODE(DoActorSlide), + SAVE_CODE(DoActorBeginJump), + SAVE_CODE(DoActorJump), + SAVE_CODE(DoActorBeginFall), + SAVE_CODE(DoActorFall), + SAVE_CODE(DoActorStopFall), + SAVE_CODE(DoActorDeathMove), + SAVE_CODE(DoBeginJump), + SAVE_CODE(DoJump), + SAVE_CODE(DoBeginFall), + SAVE_CODE(DoFall) +}; + +saveable_module saveable_actor = +{ + // code + saveable_actor_code, + SIZ(saveable_actor_code), + + // data + NULL,0 +}; diff --git a/polymer/eduke32/source/sw/src/actor.h b/polymer/eduke32/source/sw/src/actor.h new file mode 100644 index 000000000..8fb45ec94 --- /dev/null +++ b/polymer/eduke32/source/sw/src/actor.h @@ -0,0 +1,8 @@ +int DoBeginJump(short SpriteNum); +int DoJump(short SpriteNum); +int DoBeginFall(short SpriteNum); +int DoFall(short SpriteNum); +void KeepActorOnFloor(short SpriteNum); +int DoActorSlide(short SpriteNum); +int DoActorSectorDamage(short SpriteNum); +int DoScaleSprite(short SpriteNum); diff --git a/polymer/eduke32/source/sw/src/ai.c b/polymer/eduke32/source/sw/src/ai.c new file mode 100644 index 000000000..09ac6cb09 --- /dev/null +++ b/polymer/eduke32/source/sw/src/ai.c @@ -0,0 +1,2231 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "game.h" +#include "tags.h" +#include "sector.h" +#include "sprite.h" + +// temp - should be moved +#include "ninja.h" +#include "ai.h" + +#include "net.h" + +BOOL PlayerTakeDamage(PLAYERp, short); +ANIMATOR InitActorRunToward; +BOOL FAF_Sector(short); + +short FindTrackToPlayer(USERp u); +ANIMATORp ChooseAction(DECISION decision[]); + + +//static short ZigZagDeltaAng[] = {-200, 200}; + +// Choose between two things +short AttackOrRun = 200; + +#define CHOOSE2(value) (RANDOM_P2(1024) < (value)) + + +VOID DebugMoveHit(short SpriteNum) +{ + SPRITEp sp; + USERp u = User[SpriteNum]; + extern BOOL DebugActor; + + return; + + //if (u->ret == -1) + // printf("Hit a ledge\n"); + //else + /* + switch (TEST(u->ret, HIT_MASK)) + { + case HIT_SPRITE: + sp = &sprite[NORM_SPRITE(u->ret)]; + //DSPRINTF(ds, "Hit a Sprite %d, stat %d ", sp-sprite, (short)sp->statnum); + if (sp->statnum == STAT_MISSILE) + { + //DSPRINTF(ds, "Monster hit bullet %d, stat %d ", sp-sprite, (short)sp->statnum); + } + else + { + //DSPRINTF(ds, "Hit a Sprite %d, stat %d ", sp-sprite, (short)sp->statnum); + } + break; + case HIT_WALL: + //DSPRINTF(ds, "Hit a Wall %d ", NORM_WALL(u->ret)); + break; + case HIT_SECTOR: + //DSPRINTF(ds, "Hit a Sector %d ", NORM_SECTOR(u->ret)); + break; + } + + MONO_PRINT(ds); + */ +} + + +BOOL ActorMoveHitReact(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // Should only return TRUE if there is a reaction to what was hit that + // would cause the calling function to abort + + switch (TEST(u->ret, HIT_MASK)) + { + case HIT_SPRITE: + { + short HitSprite = NORM_SPRITE(u->ret); + SPRITEp hsp; + USERp hu; + ANIMATORp action; + + hsp = &sprite[HitSprite]; + hu = User[HitSprite]; + + + // if you ran into a player - call close range functions + if (hu && hu->PlayerP) + { + DoActorPickClosePlayer(SpriteNum); + action = ChooseAction(u->Personality->TouchTarget); + if (action) + { + (*action)(SpriteNum); + return TRUE; + } + } + break; + } + + case HIT_WALL: + { + break; + } + + case HIT_SECTOR: + { + break; + } + } + + return FALSE; +} + + +BOOL ActorFlaming(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if (u->flame >= 0) + { + int size; + SPRITEp fp = &sprite[u->flame]; + + size = SPRITEp_SIZE_Z(sp) - DIV4(SPRITEp_SIZE_Z(sp)); + + //DSPRINTF(ds,"enemy size %d, flame size %d",size>>8,SPRITEp_SIZE_Z(fp)>>8); + MONO_PRINT(ds); + + if (SPRITEp_SIZE_Z(fp) > size) + return TRUE; + } + + return FALSE; +} + +VOID +DoActorSetSpeed(short SpriteNum, BYTE speed) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + return; + + ASSERT(u->Attrib); + + u->speed = speed; + + if (ActorFlaming(SpriteNum)) + sp->xvel = u->Attrib->Speed[speed] + DIV2(u->Attrib->Speed[speed]); + else + sp->xvel = u->Attrib->Speed[speed]; +} + +/* + !AIC - Does a table lookup based on a random value from 0 to 1023. + These tables are defined at the top of all actor files such as ninja.c, + goro.c etc. +*/ + +ANIMATORp +ChooseAction(DECISION decision[]) +{ + short random_value; + short i; + + // !JIM! Here is an opportunity for some AI, instead of randomness! + random_value = RANDOM_P2(1024<<5)>>5; + + for (i = 0; TRUE; i++) + { + ASSERT(i < 10); + + if (random_value <= decision[i].range) + { + return decision[i].action; + } + } +} + +/* + !AIC - Sometimes just want the offset of the action +*/ + +short +ChooseActionNumber(short decision[]) +{ + short random_value; + short i; + + random_value = RANDOM_P2(1024<<5)>>5; + + for (i = 0; TRUE; i++) + { + if (random_value <= decision[i]) + { + return i; + } + } +} + +int +DoActorNoise(ANIMATORp Action, short SpriteNum) +{ + USERp u = User[SpriteNum]; + + if (Action == InitActorAmbientNoise) + { + PlaySpriteSound(SpriteNum, attr_ambient, v3df_follow); +// MONO_PRINT("Ambient Sound"); + } + else if (Action == InitActorAlertNoise) + { + if (u && !u->DidAlert) // This only allowed once + PlaySpriteSound(SpriteNum, attr_alert, v3df_follow); +// MONO_PRINT("Alert Sound"); + } + else if (Action == InitActorAttackNoise) + { + PlaySpriteSound(SpriteNum, attr_attack, v3df_follow); +// MONO_PRINT("Attack Sound"); + } + if (Action == InitActorPainNoise) + { + PlaySpriteSound(SpriteNum, attr_pain, v3df_follow); +// MONO_PRINT("Pain Sound"); + } + else if (Action == InitActorDieNoise) + { + PlaySpriteSound(SpriteNum, attr_die, v3df_none); +// MONO_PRINT("Die Sound"); + } + else if (Action == InitActorExtra1Noise) + { + PlaySpriteSound(SpriteNum, attr_extra1, v3df_follow); + } + else if (Action == InitActorExtra2Noise) + { + PlaySpriteSound(SpriteNum, attr_extra2, v3df_follow); + } + else if (Action == InitActorExtra3Noise) + { + PlaySpriteSound(SpriteNum, attr_extra3, v3df_follow); + } + if (Action == InitActorExtra4Noise) + { + PlaySpriteSound(SpriteNum, attr_extra4, v3df_follow); + } + if (Action == InitActorExtra5Noise) + { + PlaySpriteSound(SpriteNum, attr_extra5, v3df_follow); + } + if (Action == InitActorExtra6Noise) + { + PlaySpriteSound(SpriteNum, attr_extra6, v3df_follow); + } + + return 0; +} + +int +CanSeePlayer(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // if actor can still see the player + int look_height = SPRITEp_TOS(sp); + + ASSERT(u->tgt_sp); + + //if (FAF_Sector(sp->sectnum)) + // return(TRUE); + + if (FAFcansee(sp->x, sp->y, look_height, sp->sectnum, u->tgt_sp->x, u->tgt_sp->y, SPRITEp_UPPER(u->tgt_sp), u->tgt_sp->sectnum)) + return TRUE; + else + return FALSE; +} + +int +CanHitPlayer(short SpriteNum) +{ + USERp u = User[SpriteNum], hu; + SPRITEp sp = User[SpriteNum]->SpriteP, hp; + int hitx, hity, hitz; + short hitsect, hitwall, hitsprite; + int xvect,yvect,zvect; + short ang,ret=FALSE; + // if actor can still see the player + int zhs, zhh; + + //if (FAF_Sector(sp->sectnum)) + // return(TRUE); + + zhs = sp->z - DIV2(SPRITEp_SIZE_Z(sp)); + + hp = u->tgt_sp; + hu = User[u->tgt_sp - sprite]; + + // get angle to target + ang = getangle(hp->x - sp->x, hp->y - sp->y); + + // get x,yvect + xvect = sintable[NORM_ANGLE(ang + 512)]; + yvect = sintable[NORM_ANGLE(ang)]; + + // get zvect + zhh = hp->z - DIV2(SPRITEp_SIZE_Z(hp)); + if (hp->x - sp->x != 0) + zvect = xvect * ((zhh - zhs)/(hp->x - sp->x)); + else if (hp->y - sp->y != 0) + zvect = yvect * ((zhh - zhs)/(hp->y - sp->y)); + else + return FALSE; + + // so actors won't shoot straight up at you + // need to be a bit of a distance away + // before they have a valid shot +// if (labs(zvect / FindDistance2D(hp->x - sp->x, hp->y - sp->y)) > 200) +// return(FALSE); + + FAFhitscan(sp->x, sp->y, zhs, sp->sectnum, + xvect, + yvect, + zvect, + &hitsect, &hitwall, &hitsprite, &hitx, &hity, &hitz, CLIPMASK_MISSILE); + + if (hitsect < 0) + return FALSE; + + if (hitsprite == u->tgt_sp - sprite) + return TRUE; + + ////DSPRINTF(ds,"CanHit %s",ret ? "TRUE" : "FALSE"); + //MONO_PRINT(ds); + + return FALSE; +} + +/* + !AIC - Pick a nearby player to be the actors target +*/ + +int +DoActorPickClosePlayer(short SpriteNum) +{ + //extern short Zombies; + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int dist, near_dist = MAX_ACTIVE_RANGE, a,b,c; + short pnum; + PLAYERp pp,tp; + // if actor can still see the player + int look_height = SPRITEp_TOS(sp); + BOOL ICanSee = FALSE; + BOOL found = FALSE; + int i,nexti; + + if (u->ID == ZOMBIE_RUN_R0 && gNet.MultiGameType == MULTI_GAME_COOPERATIVE) + goto TARGETACTOR; + + // Set initial target to Player 0 + u->tgt_sp = Player->SpriteP; + + if (TEST(u->Flags2, SPR2_DONT_TARGET_OWNER)) + { + TRAVERSE_CONNECT(pnum) + { + pp = &Player[pnum]; + + if (sp->owner == pp->PlayerSprite) + continue; + + u->tgt_sp = pp->SpriteP; + break; + } + } + + + // Set initial target to the closest player + near_dist = MAX_ACTIVE_RANGE; + TRAVERSE_CONNECT(pnum) + { + pp = &Player[pnum]; + + // Zombies don't target their masters! + if (TEST(u->Flags2, SPR2_DONT_TARGET_OWNER)) + { + if (sp->owner == pp->PlayerSprite) + continue; + + if (!PlayerTakeDamage(pp, SpriteNum)) + continue; + + // if co-op don't hurt teammate + // if (gNet.MultiGameType == MULTI_GAME_COOPERATIVE && !gNet.HurtTeammate && u->spal == User[pp->PlayerSprite]->spal) + // continue; + } + + DISTANCE(sp->x, sp->y, pp->posx, pp->posy, dist, a, b, c); + + if (dist < near_dist) + { + near_dist = dist; + u->tgt_sp = pp->SpriteP; + } + } + + // see if you can find someone close that you can SEE + near_dist = MAX_ACTIVE_RANGE; + found = FALSE; + TRAVERSE_CONNECT(pnum) + { + pp = &Player[pnum]; + + // Zombies don't target their masters! + if (TEST(u->Flags2, SPR2_DONT_TARGET_OWNER)) + { + if (sp->owner == pp->PlayerSprite) + continue; + + if (!PlayerTakeDamage(pp, SpriteNum)) + continue; + + // if co-op don't hurt teammate + //if (gNet.MultiGameType == MULTI_GAME_COOPERATIVE && !gNet.HurtTeammate && u->spal == User[pp->PlayerSprite]->spal) + // continue; + } + + DISTANCE(sp->x, sp->y, pp->posx, pp->posy, dist, a, b, c); + + //ICanSee = FAFcansee(sp->x, sp->y, look_height, sp->sectnum, pp->SpriteP->x, pp->SpriteP->y, SPRITEp_UPPER(pp->SpriteP), pp->SpriteP->sectnum); + if (dist < near_dist && FAFcansee(sp->x, sp->y, look_height, sp->sectnum, pp->SpriteP->x, pp->SpriteP->y, SPRITEp_UPPER(pp->SpriteP), pp->SpriteP->sectnum)) + { + near_dist = dist; + u->tgt_sp = pp->SpriteP; + found = TRUE; + } + } + + +TARGETACTOR: + // this is only for Zombies right now + // zombie target other actors + if (!found && TEST(u->Flags2, SPR2_DONT_TARGET_OWNER)) + { + near_dist = MAX_ACTIVE_RANGE; + TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti) + { + if (i == SpriteNum) + continue; + + if (TEST(User[i]->Flags, SPR_SUICIDE|SPR_DEAD)) + continue; + + DISTANCE(sp->x, sp->y, sprite[i].x, sprite[i].y, dist, a, b, c); + + if (dist < near_dist && FAFcansee(sp->x, sp->y, look_height, sp->sectnum, sprite[i].x, sprite[i].y, SPRITEp_UPPER(&sprite[i]), sprite[i].sectnum)) + { + near_dist = dist; + u->tgt_sp = &sprite[i]; + } + } + } + + return 0; +} + +int +GetPlayerSpriteNum(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + short pnum; + PLAYERp pp; + + TRAVERSE_CONNECT(pnum) + { + pp = &Player[pnum]; + + if (pp->SpriteP == u->tgt_sp) + { + return pp->PlayerSprite; + } + } + return 0; +} + +int +CloseRangeDist(SPRITEp sp1, SPRITEp sp2) +{ + int clip1 = sp1->clipdist; + int clip2 = sp2->clipdist; + + // add clip boxes and a fudge factor +#define DIST_CLOSE_RANGE 400 + + return (clip1<<2) + (clip2<<2) + DIST_CLOSE_RANGE; +} + +int DoActorOperate(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + short nearsector, nearwall, nearsprite; + int nearhitdist; + int z[2]; + unsigned int i; + + if (u->ID == HORNET_RUN_R0 || u->ID == EEL_RUN_R0 || u->ID == BUNNY_RUN_R0) + return FALSE; + + if (u->Rot == u->ActorActionSet->Sit || u->Rot == u->ActorActionSet->Stand) + return FALSE; + + if ((u->WaitTics -= ACTORMOVETICS) > 0) + return FALSE; + + //DSPRINTF(ds,"sp->x = %ld, sp->y = %ld, sp->sector = %d, tp->x = %ld, tp->y = %ld, tp->ang = %d\n",sp->x,sp->y,sp->sectnum,tpoint->x,tpoint->y,tpoint->ang); + //MONO_PRINT(ds); + + z[0] = sp->z - SPRITEp_SIZE_Z(sp) + Z(5); + z[1] = sp->z - DIV2(SPRITEp_SIZE_Z(sp)); + + for (i = 0; i < SIZ(z); i++) + { + neartag(sp->x, sp->y, z[i], sp->sectnum, sp->ang, + &nearsector, &nearwall, &nearsprite, + &nearhitdist, 1024L, NTAG_SEARCH_LO_HI); + + //DSPRINTF(ds,"nearsector = %d, nearwall = %d, nearsprite = %d hitdist == %ld\n",nearsector,nearwall,nearsprite,nearhitdist); + //MONO_PRINT(ds); + +#if 0 // Actors don't hit switches on a whim + if (nearsprite >= 0 && nearhitdist < 1024) + { + if (OperateSprite(nearsprite, FALSE)) + { + u->WaitTics = 2 * 120; + + NewStateGroup(SpriteNum, u->ActorActionSet->Stand); + } + } +#endif + + } + + if (nearsector >= 0 && nearhitdist < 1024) + { + if (OperateSector(nearsector, FALSE)) + { + u->WaitTics = 2 * 120; + + NewStateGroup(SpriteNum, u->ActorActionSet->Sit); + } + } + + if (nearwall >= 0 && nearhitdist < 1024) + { + if (OperateWall(nearwall, FALSE)) + { + u->WaitTics = 2 * 120; + + NewStateGroup(SpriteNum, u->ActorActionSet->Stand); + } + } + return TRUE; + +} + +DECISION GenericFlaming[] = +{ + {30, InitActorAttack}, + {512, InitActorRunToward}, + {1024, InitActorRunAway}, +}; + +/* + !AIC KEY - This routine decides what the actor will do next. It is not called + every time through the loop. This would be too slow. It is only called when + the actor needs to know what to do next such as running into something or being + targeted. It makes decisions based on the distance and viewablity of its target + (u->tgt_sp). When it figures out the situatation with its target it calls + ChooseAction which does a random table lookup to decide what action to initialize. + Once this action is initialized it will be called until it can't figure out what to + do anymore and then this routine is called again. +*/ + +ANIMATORp +DoActorActionDecide(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int dist; + short pnum; + ANIMATORp action; + PLAYERp pp; + USERp pu=NULL; + BOOL ICanSee=FALSE; + + // REMINDER: This function is not even called if SpriteControl doesn't let + // it get called + + ASSERT(u->Personality); + + u->Dist = 0; + action = InitActorDecide; + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + //CON_Message("Jumping or falling"); + return action; + } + + // everybody on fire acts like this + if (ActorFlaming(SpriteNum)) + { + action = ChooseAction(&GenericFlaming[0]); + //CON_Message("On Fire"); + return action; + } + + + ICanSee = CanSeePlayer(SpriteNum); // Only need to call once + // But need the result multiple times + + // !AIC KEY - If aware of player - var is changed in SpriteControl + if (TEST(u->Flags, SPR_ACTIVE)) + { + // CODE BELOW = CRAP, DON'T USE IT OR IT MAKES ACTORS NOT ANIMATE SOMETIMES!!!!! + // If target was actor, retarget to player it actor died + // or just randomly give the target actor a break + //if ((User[u->tgt_sp-sprite] && + // User[u->tgt_sp-sprite]->Health <= 0) || RANDOM_RANGE(1000) > 950) + // { + // DoActorPickClosePlayer(SpriteNum); + // InitActorReposition(SpriteNum); + // return(action); + // } + + // Try to operate stuff + DoActorOperate(SpriteNum); + + // if far enough away and cannot see the player + dist = Distance(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y); + + if (dist > 30000 && !ICanSee) + { + // Enemy goes inactive - he is still allowed to roam about for about + // 5 seconds trying to find another player before his active_range is + // bumped down + SetEnemyInactive(SpriteNum); + + // You've lost the player - now decide what to do + action = ChooseAction(u->Personality->LostTarget); + //CON_Message("LostTarget"); + return action; + } + + + pu = User[GetPlayerSpriteNum(SpriteNum)]; + // check for short range attack possibility + if ((dist < CloseRangeDist(sp, u->tgt_sp) && ICanSee) || + (pu && pu->WeaponNum == WPN_FIST && u->ID != RIPPER2_RUN_R0 && u->ID != RIPPER_RUN_R0)) + { + if ((u->ID == COOLG_RUN_R0 && TEST(sp->cstat, CSTAT_SPRITE_TRANSLUCENT)) || TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) + action = ChooseAction(u->Personality->Evasive); + else + action = ChooseAction(u->Personality->CloseRange); + //CON_Message("CloseRange"); + return action; + } + + // if player is facing me and I'm being attacked + if (FACING(sp, u->tgt_sp) && TEST(u->Flags, SPR_ATTACKED) && ICanSee) + { + // if I'm a target - at least one missile comming at me + if (TEST(u->Flags, SPR_TARGETED)) + { + // not going to evade, reset the target bit + RESET(u->Flags, SPR_TARGETED); // as far as actor + // knows, its not a + // target any more + if (u->ActorActionSet->Duck && RANDOM_P2(1024<<8)>>8 < 100) + action = InitActorDuck; + else + { + if ((u->ID == COOLG_RUN_R0 && TEST(sp->cstat, CSTAT_SPRITE_TRANSLUCENT)) || TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) + action = ChooseAction(u->Personality->Evasive); + else + action = ChooseAction(u->Personality->Battle); + } + //CON_Message("Battle 1"); + return action; + } + // if NOT a target - don't bother with evasive action and start + // fighting + else + { + if ((u->ID == COOLG_RUN_R0 && TEST(sp->cstat, CSTAT_SPRITE_TRANSLUCENT)) || TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) + action = ChooseAction(u->Personality->Evasive); + else + action = ChooseAction(u->Personality->Battle); + //CON_Message("Battle 2"); + return action; + } + + } + // if player is NOT facing me he is running or unaware of actor + else if (ICanSee) + { + if ((u->ID == COOLG_RUN_R0 && TEST(sp->cstat, CSTAT_SPRITE_TRANSLUCENT)) || TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) + action = ChooseAction(u->Personality->Evasive); + else + action = ChooseAction(u->Personality->Offense); + //CON_Message("Offense"); + return action; + } + else + { + // You've lost the player - now decide what to do + action = ChooseAction(u->Personality->LostTarget); + //CON_Message("Close but cant see, LostTarget"); + return action; + } + } + // Not active - not aware of player and cannot see him + else + { + // try and find another player + // pick a closeby player as the (new) target + if (sp->hitag != TAG_SWARMSPOT) + DoActorPickClosePlayer(SpriteNum); + + // if close by + dist = Distance(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y); + if (dist < 15000 || ICanSee) + { + if ((FACING(sp, u->tgt_sp) && dist < 10000) || ICanSee) + { + DoActorOperate(SpriteNum); + + // Don't let player completely sneek up behind you + action = ChooseAction(u->Personality->Surprised); + //CON_Message("Surprised"); + if (!u->DidAlert && ICanSee) + { + DoActorNoise(InitActorAlertNoise, SpriteNum); + u->DidAlert = TRUE; + } + return action; + + } + else + { + // Player has not seen actor, to be fair let him know actor + // are there + DoActorNoise(ChooseAction(u->Personality->Broadcast),SpriteNum); + //CON_Message("Actor Noise"); + return action; + } + } + } + + //CON_Message("Couldn't resolve decide, InitActorDecide"); + return action; +} + +/* + !AIC - Setup to do the decision +*/ + + +int +InitActorDecide(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // NOTE: It is possible to overflow the stack with too many calls to this + // routine + // Should use: + // u->ActorActionFunc = DoActorDecide; + // Instead of calling this function direcly + + // MONO_PRINT(strcpy(ds,"Init Actor Stay Put")); + + u->ActorActionFunc = DoActorDecide; + + DoActorDecide(SpriteNum); + + return 0; +} + +int +DoActorDecide(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + ANIMATORp actor_action; + + // DoActorTest(SpriteNum); + + // See what to do next + actor_action = DoActorActionDecide(SpriteNum); + + // Fix for the GenericFlaming bug for actors that don't have attack states + if (actor_action == InitActorAttack && u->WeaponNum == 0) + return 0; // Just let the actor do as it was doing before in this case + + + // zombie is attacking a player + if (actor_action == InitActorAttack && u->ID == ZOMBIE_RUN_R0 && User[u->tgt_sp-sprite]->PlayerP) + { + // Don't let zombies shoot at master + if (sp->owner == (u->tgt_sp - sprite)) + return 0; + + // if this player cannot take damage from this zombie(weapon) return out + if (!PlayerTakeDamage(User[u->tgt_sp-sprite]->PlayerP, SpriteNum)) + return 0; + } + + ASSERT(actor_action != NULL); + + if (actor_action != InitActorDecide) + { + // NOT staying put + (*actor_action)(SpriteNum); + //CON_Message("DoActorDecide: NOT Staying put"); + } + else + { + // Actually staying put + NewStateGroup(SpriteNum, u->ActorActionSet->Stand); + //CON_Message("DoActorDecide: Staying put"); + } + + return 0; +} + +int +InitActorAlertNoise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + // MONO_PRINT(strcpy(ds,"Init Actor Threat Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + + +int +InitActorAmbientNoise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorAttackNoise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorPainNoise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorDieNoise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorExtra1Noise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorExtra2Noise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorExtra3Noise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorExtra4Noise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorExtra5Noise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorExtra6Noise(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + // MONO_PRINT(strcpy(ds,"Init Actor Move Noise")); + + // make some sort of noise here + + // InitActorDecide(SpriteNum); + u->ActorActionFunc = DoActorDecide; + + return 0; +} + + +/* + !AIC KEY - Routines handle moving toward the player. +*/ + +int +InitActorMoveCloser(short SpriteNum) +{ + USERp u = User[SpriteNum]; + + //MONO_PRINT("Init Actor Move Closer\n"); + + u->ActorActionFunc = DoActorMoveCloser; + + if (u->Rot != u->ActorActionSet->Run) + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int +DoActorCantMoveCloser(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //MONO_PRINT("Can't move closer\n"); + + u->track = FindTrackToPlayer(u); + + if (u->track >= 0) + { + sp->ang = getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y); + + DoActorSetSpeed(SpriteNum, MID_SPEED); + SET(u->Flags, SPR_FIND_PLAYER); + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + //MONO_PRINT("Trying to get to the track point\n"); + } + else + { + int InitActorReposition(short SpriteNum); + + // Try to move closer + //MONO_PRINT("Move Closer - Trying to move around\n"); + + InitActorReposition(SpriteNum); + } + return 0; +} + +int +DoActorMoveCloser(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int nx, ny; + + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + // if cannot move the sprite + if (!move_actor(SpriteNum, nx, ny, 0L)) + { + DebugMoveHit(SpriteNum); + + if (ActorMoveHitReact(SpriteNum)) + return 0; + + DoActorCantMoveCloser(SpriteNum); + return 0; + } + + // Do a noise if ok + DoActorNoise(ChooseAction(u->Personality->Broadcast),SpriteNum); + +#if 0 + // evasion if targeted + if (TEST(u->Flags, SPR_TARGETED)) + { + ANIMATORp action; + + action = ChooseAction(u->Personality->Evasive); + if (action) + { + (*action)(SpriteNum); + return 0; + } + } +#endif + + // after moving a ways check to see if player is still in sight + if (u->DistCheck > 550) + { + u->DistCheck = 0; + + // If player moved out of sight + if (!CanSeePlayer(SpriteNum)) + { + // stay put and choose another option + InitActorDecide(SpriteNum); + return 0; + } + else + { + // turn to face player + sp->ang = getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y); + } + } + + // Should be a random value test + if (u->Dist > 512 * 3) + { + InitActorDecide(SpriteNum); + } + + return 0; + +} + +/* + !AIC - Find tracks of different types. Toward target, away from target, etc. +*/ + + +short +FindTrackToPlayer(USERp u) +{ + SPRITEp sp = u->SpriteP; + + short point, track_dir, track; + short i, *type, size; + int zdiff; + + static short PlayerAbove[] = + { + BIT(TT_LADDER), + BIT(TT_STAIRS), + BIT(TT_JUMP_UP), + BIT(TT_TRAVERSE), + BIT(TT_OPERATE), + BIT(TT_SCAN) + }; + + static short PlayerBelow[] = + { + BIT(TT_JUMP_DOWN), + BIT(TT_STAIRS), + BIT(TT_TRAVERSE), + BIT(TT_OPERATE), + BIT(TT_SCAN) + }; + + static short PlayerOnLevel[] = + { + BIT(TT_DUCK_N_SHOOT), + BIT(TT_HIDE_N_SHOOT), + BIT(TT_TRAVERSE), + BIT(TT_EXIT), + BIT(TT_OPERATE), + BIT(TT_SCAN) + }; + + //MONO_PRINT("FindTrackToPlayer\n"); + + zdiff = SPRITEp_UPPER(u->tgt_sp) - (sp->z - SPRITEp_SIZE_Z(sp) + Z(8)); + + if (labs(zdiff) <= Z(20)) + { + type = PlayerOnLevel; + size = SIZ(PlayerOnLevel); + } + else + { + if (zdiff < 0) + { + type = PlayerAbove; + size = SIZ(PlayerAbove); + } + else + { + type = PlayerBelow; + size = SIZ(PlayerBelow); + } + } + + + for (i = 0; i < size; i++) + { + track = ActorFindTrack(u->SpriteNum, 1, type[i], &point, &track_dir); + + if (track >= 0) + { + u->point = point; + u->track_dir = track_dir; + SET(Track[track].flags, TF_TRACK_OCCUPIED); + + ////DSPRINTF(ds, "Found Track To Player\n"); + //MONO_PRINT(ds); + + return track; + } + } + + return -1; + +} + + + +short +FindTrackAwayFromPlayer(USERp u) +{ + SPRITEp sp = u->SpriteP; + + short point, track_dir, track; + unsigned int i; + + static short RunAwayTracks[] = + { + BIT(TT_EXIT), + BIT(TT_LADDER), + BIT(TT_TRAVERSE), + BIT(TT_STAIRS), + BIT(TT_JUMP_UP), + BIT(TT_JUMP_DOWN), + BIT(TT_DUCK_N_SHOOT), + BIT(TT_HIDE_N_SHOOT), + BIT(TT_OPERATE), + BIT(TT_SCAN) + }; + + //MONO_PRINT("FindTrackAwayFromPlayer\n"); + + for (i = 0; i < SIZ(RunAwayTracks); i++) + { + track = ActorFindTrack(u->SpriteNum, -1, RunAwayTracks[i], &point, &track_dir); + + if (track >= 0) + { + u->point = point; + u->track_dir = track_dir; + SET(Track[track].flags, TF_TRACK_OCCUPIED); + + ////DSPRINTF(ds, "Found Run Away Track\n"); + //MONO_PRINT(ds); + + return track; + } + //MONO_PRINT("Did not find a run away track!\n"); + } + + return -1; + +} + + +short +FindWanderTrack(USERp u) +{ + SPRITEp sp = u->SpriteP; + + short point, track_dir, track; + unsigned int i; + + static short WanderTracks[] = + { + BIT(TT_DUCK_N_SHOOT), + BIT(TT_HIDE_N_SHOOT), + BIT(TT_WANDER), + BIT(TT_JUMP_DOWN), + BIT(TT_JUMP_UP), + BIT(TT_TRAVERSE), + BIT(TT_STAIRS), + BIT(TT_LADDER), + BIT(TT_EXIT), + BIT(TT_OPERATE) + }; + + //MONO_PRINT("FindWanderTrack\n"); + + for (i = 0; i < SIZ(WanderTracks); i++) + { + track = ActorFindTrack(u->SpriteNum, -1, WanderTracks[i], &point, &track_dir); + + if (track >= 0) + { + u->point = point; + u->track_dir = track_dir; + SET(Track[track].flags, TF_TRACK_OCCUPIED); + + return track; + } + } + + return -1; +} + + +int +InitActorRunAway(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //MONO_PRINT("Init Actor RunAway\n"); + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + u->track = FindTrackAwayFromPlayer(u); + + if (u->track >= 0) + { + sp->ang = NORM_ANGLE(getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y)); + DoActorSetSpeed(SpriteNum, FAST_SPEED); + SET(u->Flags, SPR_RUN_AWAY); + //MONO_PRINT("Actor running away on track\n"); + } + else + { + SET(u->Flags, SPR_RUN_AWAY); + InitActorReposition(SpriteNum); + ////DSPRINTF(ds, "Actor RunAway\n"); + //MONO_PRINT(ds); + } + + return 0; +} + +int +InitActorRunToward(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //MONO_PRINT("InitActorRunToward\n"); + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + InitActorReposition(SpriteNum); + DoActorSetSpeed(SpriteNum, FAST_SPEED); + + return 0; +} + +/* + !AIC - Where actors do their attacks. There is some special case code throughout + these. Both close and long range attacks are handled here by transitioning to + the correct attack state. +*/ + + +int +InitActorAttack(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // zombie is attacking a player + if (u->ID == ZOMBIE_RUN_R0 && User[u->tgt_sp-sprite]->PlayerP) + { + // Don't let zombies shoot at master + if (sp->owner == (u->tgt_sp - sprite)) + return 0; + + // if this player cannot take damage from this zombie(weapon) return out + if (!PlayerTakeDamage(User[u->tgt_sp-sprite]->PlayerP, SpriteNum)) + return 0; + } + + if (TEST(sprite[u->tgt_sp-sprite].cstat, CSTAT_SPRITE_TRANSLUCENT)) + { + InitActorRunAway(SpriteNum); + return 0; + } + + if (User[u->tgt_sp-sprite] && + User[u->tgt_sp-sprite]->Health <= 0) + { + DoActorPickClosePlayer(SpriteNum); + InitActorReposition(SpriteNum); + return 0; + } + + if (!CanHitPlayer(SpriteNum)) + { + InitActorReposition(SpriteNum); + return 0; + } + + // if the guy you are after is dead, look for another and + // reposition + if (User[u->tgt_sp-sprite] && + User[u->tgt_sp-sprite]->PlayerP && + TEST(User[u->tgt_sp-sprite]->PlayerP->Flags, PF_DEAD)) + { + DoActorPickClosePlayer(SpriteNum); + InitActorReposition(SpriteNum); + return 0; + } + + u->ActorActionFunc = DoActorAttack; + + // move into standing frame + //NewStateGroup(SpriteNum, u->ActorActionSet->Stand); + + // face player when attacking + sp->ang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y)); + + // If it's your own kind, lay off! + if (u->ID == User[u->tgt_sp - sprite]->ID && !User[u->tgt_sp - sprite]->PlayerP) + { + InitActorRunAway(SpriteNum); + return 0; + } + +#if 0 + // if low on health determine if needs to run away + if (u->Health < 26) + { + if (CHOOSE2(AttackOrRun)) + { + InitActorRunAway(SpriteNum); + + // could do a FindHealth here + + return 0; + } + + } +#endif + + // Hari Kari for Ninja's + if (u->ActorActionSet->Death2) + { + //#define SUICIDE_HEALTH_VALUE 26 +#define SUICIDE_HEALTH_VALUE 38 + extern STATEp sg_NinjaGrabThroat[]; + //#define SUICIDE_HEALTH_VALUE 50 + + if (u->Health < SUICIDE_HEALTH_VALUE) + { + if (CHOOSE2(100)) + { + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Death2); + return 0; + } + } + } + + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + + +int +DoActorAttack(short SpriteNum) +{ + USERp u = User[SpriteNum],pu; + SPRITEp sp = User[SpriteNum]->SpriteP; + short rand_num; + int dist,a,b,c; + + DoActorNoise(ChooseAction(u->Personality->Broadcast),SpriteNum); + + DISTANCE(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y, dist, a, b, c); + + pu = User[GetPlayerSpriteNum(SpriteNum)]; + if ((u->ActorActionSet->CloseAttack[0] && dist < CloseRangeDist(sp, u->tgt_sp)) || + (pu && pu->WeaponNum == WPN_FIST)) // JBF: added null check + { + rand_num = ChooseActionNumber(u->ActorActionSet->CloseAttackPercent); + + NewStateGroup(SpriteNum, u->ActorActionSet->CloseAttack[rand_num]); + } + else + { + ASSERT(u->WeaponNum != 0); + + rand_num = ChooseActionNumber(u->ActorActionSet->AttackPercent); + + ASSERT(rand_num < u->WeaponNum); + + NewStateGroup(SpriteNum, u->ActorActionSet->Attack[rand_num]); + u->ActorActionFunc = DoActorDecide; + } + + //u->ActorActionFunc = DoActorDecide; + + return 0; +} + +int +InitActorEvade(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //MONO_PRINT("Init Actor Evade\n"); + + // Evade is same thing as run away except when you get to the end of the + // track + // you stop and take up the fight again. + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + u->track = FindTrackAwayFromPlayer(u); + + if (u->track >= 0) + { + sp->ang = NORM_ANGLE(getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y)); + DoActorSetSpeed(SpriteNum, FAST_SPEED); + // NOT doing a RUN_AWAY + RESET(u->Flags, SPR_RUN_AWAY); + } + + return 0; +} + +int +InitActorWanderAround(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //DSPRINTF(ds, "InitActorWanderAround\n"); + //MONO_PRINT(ds); + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + DoActorPickClosePlayer(SpriteNum); + + u->track = FindWanderTrack(u); + + if (u->track >= 0) + { + sp->ang = getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y); + DoActorSetSpeed(SpriteNum, NORM_SPEED); + } + + return 0; +} + +int +InitActorFindPlayer(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int DoActorFindPlayer(short SpriteNum); + + //DSPRINTF(ds, "InitActorFindPlayer\n"); + //MONO_PRINT(ds); + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + u->track = FindTrackToPlayer(u); + + if (u->track >= 0) + { + sp->ang = getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y); + DoActorSetSpeed(SpriteNum, MID_SPEED); + SET(u->Flags, SPR_FIND_PLAYER); + + u->ActorActionFunc = DoActorDecide; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + } + else + { + InitActorReposition(SpriteNum); + } + + + return 0; +} + +int +InitActorDuck(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + short dist; + +// MONO_PRINT(strcpy(ds, "Init Actor Duck")); + + if (!u->ActorActionSet->Duck) + { + u->ActorActionFunc = DoActorDecide; + return 0; + } + + u->ActorActionFunc = DoActorDuck; + NewStateGroup(SpriteNum, u->ActorActionSet->Duck); + + dist = Distance(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y); + + if (dist > 8000) + { + u->WaitTics = 190; + } + else + { + //u->WaitTics = 120; + u->WaitTics = 60; + } + + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int +DoActorDuck(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if ((u->WaitTics -= ACTORMOVETICS) < 0) + { + NewStateGroup(SpriteNum, u->ActorActionSet->Rise); + u->ActorActionFunc = DoActorDecide; + // InitActorDecide(SpriteNum); + RESET(u->Flags, SPR_TARGETED); + } + + return 0; +} + +int +DoActorMoveJump(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int nx, ny; + + // Move while jumping + + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + move_actor(SpriteNum, nx, ny, 0L); + + if (!TEST(u->Flags, SPR_JUMPING|SPR_FALLING)) + { + InitActorDecide(SpriteNum); + } + + return 0; +} + + +int move_scan(short SpriteNum, short ang, int dist, int *stopx, int *stopy, int *stopz, short *stopsect) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + int nx,ny; + ULONG cliptype = CLIPMASK_ACTOR; + int ret; + + short sang,ss; + int x, y, z, loz, hiz; + SPRITEp lo_sp, hi_sp; + SECTORp lo_sectp, hi_sectp; + + + // moves out a bit but keeps the sprites original postion/sector. + + // save off position info + x = sp->x; + y = sp->y; + z = sp->z; + sang = sp->ang; + loz = u->loz; + hiz = u->hiz; + lo_sp = u->lo_sp; + hi_sp = u->hi_sp; + lo_sectp = u->lo_sectp; + hi_sectp = u->hi_sectp; + ss = sp->sectnum; + + // do the move + sp->ang = ang; + nx = (dist) * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = (dist) * (int) sintable[sp->ang] >> 14; + + ret = move_sprite(SpriteNum, nx, ny, 0, u->ceiling_dist, u->floor_dist, cliptype, 1); + // move_sprite DOES do a getzrange point? + + // should I look down with a FAFgetzrange to see where I am? + + // remember where it stopped + *stopx = sp->x; + *stopy = sp->y; + *stopz = sp->z; + *stopsect = sp->sectnum; + + // reset position information + sp->x = x; + sp->y = y; + sp->z = z; + sp->ang = sang; + u->loz = loz; + u->hiz = hiz; + u->lo_sp = lo_sp; + u->hi_sp = hi_sp; + u->lo_sectp = lo_sectp; + u->hi_sectp = hi_sectp; + changespritesect(SpriteNum, ss); + + return ret; +} + +#define TOWARD 1 +#define AWAY -1 + +int +FindNewAngle(short SpriteNum, signed char dir, int DistToMove) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + BOOL DropAhead(short SpriteNum, short min_height); + + static short toward_angle_delta[4][9] = + { + { -160, -384, 160, 384, -256, 256, -512, 512, -99}, + { -384, -160, 384, 160, -256, 256, -512, 512, -99}, + { 160, 384, -160, -384, 256, -256, 512, -512, -99}, + { 384, 160, -384, -160, 256, -256, 512, -512, -99} + }; + + static short away_angle_delta[4][8] = + { + { -768, 768, -640, 640, -896, 896, 1024, -99}, + { 768, -768, 640, -640, -896, 896, 1024, -99}, + { 896, -896, -768, 768, -640, 640, 1024, -99}, + { 896, -896, 768, -768, 640, -640, 1024, -99} + }; + + + SHORTp adp = NULL; + + short new_ang, oang; + short save_ang = -1; + unsigned short ret; + int set; + + int dist, stopx, stopy, stopz; + short stopsect; + // start out with mininum distance that will be accepted as a move + int save_dist = 500; + + // if on fire, run shorter distances + if (ActorFlaming(SpriteNum)) + DistToMove = DIV4(DistToMove) + DIV8(DistToMove); + + // Find angle to from the player + oang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y)); + + // choose a random angle array + switch (dir) + { + case TOWARD: + set = RANDOM_P2(4<<8)>>8; + adp = &toward_angle_delta[set][0]; + break; + case AWAY: + set = RANDOM_P2(4<<8)>>8; + if (CanHitPlayer(SpriteNum)) + { + adp = &toward_angle_delta[set][0]; + } + else + { + adp = &away_angle_delta[set][0]; + } + break; + default: + printf("FindNewAngle called with dir=%d!\n",dir); + return 0; + } + + for (; *adp != -99; adp++) + { + new_ang = NORM_ANGLE(oang + *adp); + +#if 1 + // look directly ahead for a ledge + if (!TEST(u->Flags, SPR_NO_SCAREDZ | SPR_JUMPING | SPR_FALLING | SPR_SWIMMING | SPR_DEAD)) + { + sp->ang = new_ang; + if (DropAhead(SpriteNum, u->lo_step)) + { + sp->ang = oang; + continue; + } + sp->ang = oang; + } +#endif + + // check to see how far we can move + ret = move_scan(SpriteNum, new_ang, DistToMove, &stopx, &stopy, &stopz, &stopsect); + + if (ret == 0) + { + // cleanly moved in new direction without hitting something + u->TargetDist = Distance(sp->x, sp->y, stopx, stopy); + return new_ang; + } + else + { + // hit something + dist = Distance(sp->x, sp->y, stopx, stopy); + + if (dist > save_dist) + { + save_ang = new_ang; + save_dist = dist; + } + } + } + + if (save_ang != -1) + { + u->TargetDist = save_dist; + + // If actor moved to the TargetDist it would look like he was running + // into things. + + // To keep this from happening make the TargetDist is less than the + // point you would hit something + + if (u->TargetDist > 4000) + u->TargetDist -= 3500; + + sp->ang = save_ang; + return save_ang; + } + + return -1; +} + + +/* + + !AIC KEY - Reposition code is called throughout this file. What this does is + pick a new direction close to the target direction (or away from the target + direction if running away) and a distance to move in and tries to move there + with move_scan(). If it hits something it will try again. No movement is + actually acomplished here. This is just testing for clear paths to move in. + Location variables that are changed are saved and reset. FindNewAngle() and + move_scan() are two routines (above) that go with this. This is definately + not called every time through the loop. It would be majorly slow. + +*/ + +#define REPOSITION 2 + +#if REPOSITION == 2 +int +InitActorReposition(short SpriteNum) +{ + int DoActorReposition(short SpriteNum); + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + short ang; + int rnum; + int dist; + + static int AwayDist[8] = + { + 17000, + 20000, + 26000, + 26000, + 26000, + 32000, + 32000, + 42000 + }; + + static int TowardDist[8] = + { + 10000, + 15000, + 20000, + 20000, + 25000, + 30000, + 35000, + 40000 + }; + + static int PlayerDist[8] = + { + 2000, + 3000, + 3000, + 5000, + 5000, + 5000, + 9000, + 9000 + }; + + //MONO_PRINT("InitActorReposition\n"); + + u->Dist = 0; + + rnum = RANDOM_P2(8<<8)>>8; + dist = Distance(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y); + + if (dist < PlayerDist[rnum] || TEST(u->Flags, SPR_RUN_AWAY)) + { + rnum = RANDOM_P2(8<<8)>>8; + ang = FindNewAngle(SpriteNum, AWAY, AwayDist[rnum]); + if (ang == -1) + { + u->Vis = 8; + InitActorPause(SpriteNum); + return 0; + } + + sp->ang = ang; + DoActorSetSpeed(SpriteNum, FAST_SPEED); + RESET(u->Flags, SPR_RUN_AWAY); + } + else + { + // try to move toward player + rnum = RANDOM_P2(8<<8)>>8; + ang = FindNewAngle(SpriteNum, TOWARD, TowardDist[rnum]); + if (ang == -1) + { + // try to move away from player + rnum = RANDOM_P2(8<<8)>>8; + ang = FindNewAngle(SpriteNum, AWAY, AwayDist[rnum]); + if (ang == -1) + { + u->Vis = 8; + InitActorPause(SpriteNum); + return 0; + } + } + else + { + // pick random speed to move toward the player + if (RANDOM_P2(1024) < 512) + DoActorSetSpeed(SpriteNum, NORM_SPEED); + else + DoActorSetSpeed(SpriteNum, MID_SPEED); + } + + sp->ang = ang; + } + + + u->ActorActionFunc = DoActorReposition; + if (!TEST(u->Flags, SPR_SWIMMING)) + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int +DoActorReposition(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int nx, ny; + + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + // still might hit something and have to handle it. + if (!move_actor(SpriteNum, nx, ny, 0L)) + { + if (ActorMoveHitReact(SpriteNum)) + return 0; + + u->Vis = 6; + InitActorPause(SpriteNum); + return 0; + } + + // if close to target distance do a Decision again + if (u->TargetDist < 50) + { + InitActorDecide(SpriteNum); + } + + return 0; +} + + +int +InitActorPause(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + u->ActorActionFunc = DoActorPause; + + // !JIM! This makes actors not animate + //if (!TEST(u->Flags, SPR_SWIMMING)) + //NewStateGroup(SpriteNum, u->ActorActionSet->Stand); + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int +DoActorPause(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + // Using Vis instead of WaitTics, var name sucks, but it's the same type + // WaitTics is used by too much other actor code and causes problems here + if ((u->Vis -= ACTORMOVETICS) < 0) + { + u->ActorActionFunc = DoActorDecide; + RESET(u->Flags, SPR_TARGETED); + } + + return 0; +} +#endif + +// not used - simplified version that is purely random that is easier to follow +// just leaving it here to look at +#if REPOSITION == 1 +int +InitActorReposition(short SpriteNum) +{ + int DoActorReposition(short SpriteNum); + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //MONO_PRINT("InitActorReposition\n"); + + u->WaitTics = 8; + sp->ang = RANDOM_P2(2048); + + u->ActorActionFunc = DoActorReposition; + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int +DoActorReposition(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + int nx, ny; + + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + if (!move_actor(SpriteNum, nx, ny, 0L)) + { + if (ActorMoveHitReact(SpriteNum)) + return 0; + + InitActorPause(SpriteNum); + return 0; + } + + return 0; +} + + +int +InitActorPause(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + //MONO_PRINT("InitActorPause\n"); + + u->ActorActionFunc = DoActorPause; + + //NewStateGroup(SpriteNum, u->ActorActionSet->Stand); + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int +DoActorPause(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if ((u->WaitTics -= ACTORMOVETICS) < 0) + { + u->ActorActionFunc = DoActorDecide; + RESET(u->Flags, SPR_TARGETED); + } + + return 0; +} +#endif + + +#include "saveable.h" + +static saveable_code saveable_ai_code[] = +{ + SAVE_CODE(DebugMoveHit), + SAVE_CODE(ActorMoveHitReact), + SAVE_CODE(ActorFlaming), + SAVE_CODE(DoActorSetSpeed), + SAVE_CODE(ChooseAction), + SAVE_CODE(ChooseActionNumber), + SAVE_CODE(DoActorNoise), + SAVE_CODE(CanSeePlayer), + SAVE_CODE(CanHitPlayer), + SAVE_CODE(DoActorPickClosePlayer), + SAVE_CODE(GetPlayerSpriteNum), + SAVE_CODE(CloseRangeDist), + SAVE_CODE(DoActorOperate), + SAVE_CODE(DoActorActionDecide), + SAVE_CODE(InitActorDecide), + SAVE_CODE(DoActorDecide), + SAVE_CODE(InitActorAlertNoise), + SAVE_CODE(InitActorAmbientNoise), + SAVE_CODE(InitActorAttackNoise), + SAVE_CODE(InitActorPainNoise), + SAVE_CODE(InitActorDieNoise), + SAVE_CODE(InitActorExtra1Noise), + SAVE_CODE(InitActorExtra2Noise), + SAVE_CODE(InitActorExtra3Noise), + SAVE_CODE(InitActorExtra4Noise), + SAVE_CODE(InitActorExtra5Noise), + SAVE_CODE(InitActorExtra6Noise), + SAVE_CODE(InitActorMoveCloser), + SAVE_CODE(DoActorCantMoveCloser), + SAVE_CODE(DoActorMoveCloser), + SAVE_CODE(FindTrackToPlayer), + SAVE_CODE(FindTrackAwayFromPlayer), + SAVE_CODE(FindWanderTrack), + SAVE_CODE(InitActorRunAway), + SAVE_CODE(InitActorRunToward), + SAVE_CODE(InitActorAttack), + SAVE_CODE(DoActorAttack), + SAVE_CODE(InitActorEvade), + SAVE_CODE(InitActorWanderAround), + SAVE_CODE(InitActorFindPlayer), + SAVE_CODE(InitActorDuck), + SAVE_CODE(DoActorDuck), + SAVE_CODE(DoActorMoveJump), + SAVE_CODE(FindNewAngle), + SAVE_CODE(InitActorReposition), + SAVE_CODE(DoActorReposition), + SAVE_CODE(InitActorPause), + SAVE_CODE(DoActorPause) +}; + +static saveable_data saveable_ai_data[] = +{ + SAVE_DATA(GenericFlaming) +}; + +saveable_module saveable_ai = +{ + // code + saveable_ai_code, + SIZ(saveable_ai_code), + + // data + saveable_ai_data, + SIZ(saveable_ai_data) +}; diff --git a/polymer/eduke32/source/sw/src/ai.h b/polymer/eduke32/source/sw/src/ai.h new file mode 100644 index 000000000..7c1994dac --- /dev/null +++ b/polymer/eduke32/source/sw/src/ai.h @@ -0,0 +1,166 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifndef AI_H + +#define AI_H + +// Call functions based on a random range value +typedef struct +{ + short range; + ANIMATORp action; +} DECISION, *DECISIONp; + +// Personality structure +struct PERSONALITYstruct +{ + DECISIONp Battle; + DECISIONp Offense; + DECISIONp Broadcast; + DECISIONp Surprised; + DECISIONp Evasive; + DECISIONp LostTarget; + DECISIONp CloseRange; + DECISIONp TouchTarget; +}; + +enum ActorStates { SLOW_SPEED, NORM_SPEED, MID_SPEED, FAST_SPEED, MAX_SPEED}; + +#define MAXATTRIBSNDS 11 +typedef enum +{ + attr_ambient, attr_alert, attr_attack, attr_pain, attr_die, + attr_extra1, attr_extra2, attr_extra3,attr_extra4,attr_extra5, + attr_extra6 +} ATTRIB_SNDS; + +struct ATTRIBUTEstruct +{ + short Speed[MAX_SPEED]; + CHAR TicAdjust[MAX_SPEED]; + BYTE MaxWeapons; + /*ATTRIB_SNDS*/ int Sounds[MAXATTRIBSNDS]; // JBF: ATTRIB_SNDS? Somehow I don't think this is what was intended... +}; + +extern ATTRIBUTE DefaultAttrib; + +// AI.C functions +void DebugMoveHit(short SpriteNum); +BOOL ActorMoveHitReact(short SpriteNum); +BOOL ActorFlaming(short SpriteNum); +void DoActorSetSpeed(short SpriteNum,BYTE speed); +short ChooseActionNumber(short decision[]); +int DoActorNoise(ANIMATORp Action,short SpriteNum); +int CanSeePlayer(short SpriteNum); +int CanHitPlayer(short SpriteNum); +int DoActorPickClosePlayer(short SpriteNum); +int CloseRangeDist(SPRITEp sp1,SPRITEp sp2); +int InitActorDecide(short SpriteNum); +int DoActorDecide(short SpriteNum); +int InitActorAlertNoise(short SpriteNum); +int InitActorAmbientNoise(short SpriteNum); +int InitActorAttackNoise(short SpriteNum); +int InitActorPainNoise(short SpriteNum); +int InitActorDieNoise(short SpriteNum); +int InitActorExtra1Noise(short SpriteNum); +int InitActorExtra2Noise(short SpriteNum); +int InitActorExtra3Noise(short SpriteNum); +int InitActorExtra4Noise(short SpriteNum); +int InitActorExtra5Noise(short SpriteNum); +int InitActorExtra6Noise(short SpriteNum); +int InitActorMoveCloser(short SpriteNum); +int DoActorCantMoveCloser(short SpriteNum); +int DoActorMoveCloser(short SpriteNum); +short FindTrackToPlayer(USERp u); +short FindTrackAwayFromPlayer(USERp u); +short FindWanderTrack(USERp u); +int InitActorRunAway(short SpriteNum); +int InitActorRunToward(short SpriteNum); +int InitActorAttack(short SpriteNum); +int DoActorAttack(short SpriteNum); +int InitActorEvade(short SpriteNum); +int InitActorWanderAround(short SpriteNum); +int InitActorFindPlayer(short SpriteNum); +int InitActorDuck(short SpriteNum); +int DoActorDuck(short SpriteNum); +int DoActorMoveJump(short SpriteNum); +int move_scan(short SpriteNum,short ang,int dist,int *stopx,int *stopy,int *stopz,short *stopsect); +int FindNewAngle(short SpriteNum,signed char dir,int DistToMove); +int InitActorReposition(short SpriteNum); +int DoActorReposition(short SpriteNum); +int InitActorPause(short SpriteNum); +int DoActorPause(short SpriteNum); + +/* +ANIMATOR +InitActorDecide, +InitActorMoveCloser, +InitActorAttack, +InitActorRunAway, +InitActorEvade, +InitActorWanderAround, +InitActorFindPlayer, +InitActorReposition, +InitActorPause, +InitActorDuck, +InitActorAmbientNoise, +InitActorAlertNoise, +InitActorAttackNoise, +InitActorPainNoise, +InitActorDieNoise, +InitActorExtra1Noise, +InitActorExtra2Noise, +InitActorExtra3Noise, +InitActorExtra4Noise, +InitActorExtra5Noise, +InitActorExtra6Noise; + +ANIMATOR +DoActorDecide, +DoActorMoveCloser, +DoActorAttack, +DoActorRunAway, +DoActorWanderAround, +DoActorReposition, +DoActorPause, +DoActorDuck, +DoActorAmbientNoise, +DoActorAlertNoise, +DoActorAttackNoise, +DoActorPainNoise, +DoActorDieNoise, +DoActorExtra1Noise, +DoActorExtra2Noise, +DoActorExtra3Noise, +DoActorExtra4Noise, +DoActorExtra5Noise, +DoActorExtra6Noise; +*/ + +VOID DoActorSetSpeed(short SpriteNum, BYTE speed); + +#endif diff --git a/polymer/eduke32/source/sw/src/ambient.h b/polymer/eduke32/source/sw/src/ambient.h new file mode 100644 index 000000000..90402935e --- /dev/null +++ b/polymer/eduke32/source/sw/src/ambient.h @@ -0,0 +1,215 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifdef AMBIENT_TABLE +#define AMB_ENTRY(name, diginame, ambient_flags, maxtics) {name, diginame, ambient_flags, maxtics}, +#endif + +#ifdef AMBIENT_ENUM +#define AMB_ENTRY(name, diginame, ambient_flags, maxtics) name, +#endif + +// Ambient Flags, flags can be added whenever needed, up to 16 bits +#define AMB_NONE 0 +#define AMB_FOLLOW 1 // 1 = Do coordinate updates on sound +// Use this only if the sprite won't be deleted soon +#define AMB_DOPPLER 4 // 1 = Don't use doppler pitch variance + +#define AMB_PAN 8 // 1 = Don't do panning of sound +#define AMB_INTERMIT 32 // 1 = This is a non-looping intermittant sound + +// Tic counts used for intermittent sounds +#define AMB_TICRATE 12 // 120/10 since it's only called 10x per second +#define AMB_NOTICS 0 +#define AMB_5 5 *AMB_TICRATE +#define AMB_10 10*AMB_TICRATE // AMB_TICRATE is the game's tic rate +#define AMB_15 15*AMB_TICRATE +#define AMB_20 20*AMB_TICRATE +#define AMB_30 30*AMB_TICRATE +#define AMB_45 45*AMB_TICRATE +#define AMB_60 60*AMB_TICRATE +#define AMB_120 120*AMB_TICRATE + + +// BUBBLES +AMB_ENTRY(0, DIGI_BUBBLES, AMB_PAN, AMB_NOTICS) + +// CRICKETS +AMB_ENTRY(1, DIGI_CRICKETS, AMB_PAN, AMB_NOTICS) + +// AMBIENT WATER DRIPPING IN CAVE +AMB_ENTRY(2, DIGI_CAVEDRIP1, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(3, DIGI_CAVEDRIP2, AMB_INTERMIT, AMB_10) +AMB_ENTRY(4, DIGI_DRIP, AMB_PAN|AMB_INTERMIT, AMB_20) + +// WATER FALL +AMB_ENTRY(5, DIGI_WATERFALL1, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(6, DIGI_WATERFALL2, AMB_NONE, AMB_NOTICS) + +// WATER FLOWING +AMB_ENTRY(7, DIGI_WATERFLOW1, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(8, DIGI_WATERFLOW2, AMB_NONE, AMB_NOTICS) + +// CRACKLING FIRE FOR CONTINUOUS BURN +AMB_ENTRY(9, DIGI_FIRE1, AMB_NONE, AMB_NOTICS) + +// POWERFULL HIGH HEAT CONTINUOUS BURN +AMB_ENTRY(10, DIGI_FIRE2, AMB_NONE, AMB_NOTICS) + +// AMBIENT GONG FOR USE IN TEMPLE/PALACE LEVELS +AMB_ENTRY(11, DIGI_GONG, AMB_INTERMIT, AMB_120) + +// AMBIENT LAVA FLOW +AMB_ENTRY(12, DIGI_LAVAFLOW1, AMB_NONE, AMB_NOTICS) + +// AMBIENT MUD BUBBLES +AMB_ENTRY(13, DIGI_MUBBUBBLES1, AMB_NONE, AMB_NOTICS) + +// AMBIENT EARTH QUAKE +AMB_ENTRY(14, DIGI_EARTHQUAKE, AMB_NONE, AMB_NOTICS) + +// YUCKY SEWER FLOW +AMB_ENTRY(15, DIGI_SEWERFLOW1, AMB_NONE, AMB_NOTICS) + +// STEAM FLOW +AMB_ENTRY(16, DIGI_STEAM1, AMB_NONE, AMB_NOTICS) + +// VOLCANIC STEAM VENT +AMB_ENTRY(17, DIGI_VOLCANOSTEAM1, AMB_NONE, AMB_NOTICS) + +// SCARY AMBIENT SWAMP SOUNDS +AMB_ENTRY(18, DIGI_SWAMP, AMB_NONE, AMB_NOTICS) + +// AMBIENT ROLLING THUNDER +AMB_ENTRY(19, DIGI_THUNDER, AMB_PAN|AMB_INTERMIT, AMB_60) + +// UNDERWATER AMBIENCE +AMB_ENTRY(20, DIGI_UNDERWATER, AMB_PAN, AMB_NOTICS) + +// SPOOKY ETHERAL VOID AMBIENCE (NETHERWORLDLY SOUNDS) +AMB_ENTRY(21, DIGI_VOID1, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(22, DIGI_VOID2, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(23, DIGI_VOID3, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(24, DIGI_VOID4, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(25, DIGI_VOID5, AMB_NONE, AMB_NOTICS) + +// VOLCANIC ERUPTION +AMB_ENTRY(26, DIGI_ERUPTION, AMB_NONE, AMB_NOTICS) + +// VOLCANIC SIZZLING PROJECTILES FLYING THROUGH AIR +AMB_ENTRY(27, DIGI_VOLCANOPROJECTILE, AMB_NONE, AMB_NOTICS) + +// LIGHT WIND AMBIENCE +AMB_ENTRY(28, DIGI_LIGHTWIND, AMB_NONE, AMB_NOTICS) + +// STRONG BLOWING WIND AMBIENCE +AMB_ENTRY(29, DIGI_STRONGWIND, AMB_PAN|AMB_INTERMIT, AMB_20) + +// BREAKING WOOD AMBIENCE +AMB_ENTRY(30, DIGI_BREAKINGWOOD, AMB_INTERMIT, AMB_120) + +// BREAKING, TUMBLING STONES FALLING AMBIENCE +AMB_ENTRY(31, DIGI_BREAKSTONES, AMB_NONE, AMB_NOTICS) + +// MOTOR BOAT +AMB_ENTRY(32, DIGI_NULL, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(33, DIGI_NULL, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(34, DIGI_NULL, AMB_NONE, AMB_NOTICS) + +// WWII JAP ARMY TANK +AMB_ENTRY(35, DIGI_NULL, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(36, DIGI_NULL, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(37, DIGI_NULL, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(38, DIGI_NULL, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(39, DIGI_NULL, AMB_NONE, AMB_NOTICS) + +// WWII JAP BOMBER PLANE +AMB_ENTRY(40, DIGI_BOMBRFLYING, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(41, DIGI_BOMBRDROPBOMB, AMB_NONE, AMB_NOTICS) + +// GIANT DRILL MACHINE +AMB_ENTRY(42, DIGI_DRILL, AMB_NONE, AMB_NOTICS) + +// SECTOR GEAR COG TURNING +AMB_ENTRY(43, DIGI_GEAR1, AMB_NONE, AMB_NOTICS) + +// GENERIC SECTOR OBJECT MACHINE RUNNING +AMB_ENTRY(44, DIGI_MACHINE1, AMB_NONE, AMB_NOTICS) + +// ENGINE ROOM +AMB_ENTRY(45, DIGI_ENGROOM1, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(46, DIGI_ENGROOM2, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(47, DIGI_ENGROOM3, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(48, DIGI_ENGROOM4, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(49, DIGI_ENGROOM5, AMB_NONE, AMB_NOTICS) + +// HELICOPTER, SPINNING BLADE SOUND +AMB_ENTRY(50, DIGI_HELI, AMB_NONE, AMB_NOTICS) + +// ECHOING HEART +AMB_ENTRY(51, DIGI_BIGHART, AMB_NONE, AMB_NOTICS) + +// ETHERAL WIND +AMB_ENTRY(52, DIGI_WIND4, AMB_NONE, AMB_NOTICS) + +// SPOOKY SINE WAVE +AMB_ENTRY(53, DIGI_SPOOKY1, AMB_NONE, AMB_NOTICS) + +// JET ENGINE +AMB_ENTRY(54, DIGI_JET, AMB_NONE, AMB_NOTICS) + +// CEREMONIAL DRUM CHANT +AMB_ENTRY(55, DIGI_DRUMCHANT, AMB_NONE, AMB_NOTICS) + +AMB_ENTRY(56, DIGI_ASIREN1, AMB_INTERMIT, AMB_45) +AMB_ENTRY(57, DIGI_FIRETRK1, AMB_INTERMIT, AMB_60) +AMB_ENTRY(58, DIGI_TRAFFIC1, AMB_INTERMIT, AMB_60) +AMB_ENTRY(59, DIGI_TRAFFIC2, AMB_INTERMIT, AMB_60) +AMB_ENTRY(60, DIGI_TRAFFIC3, AMB_INTERMIT, AMB_60) +AMB_ENTRY(61, DIGI_TRAFFIC4, AMB_INTERMIT, AMB_60) +AMB_ENTRY(62, DIGI_TRAFFIC5, AMB_INTERMIT, AMB_30) +AMB_ENTRY(63, DIGI_TRAFFIC6, AMB_INTERMIT, AMB_60) +AMB_ENTRY(64, DIGI_HELI1, AMB_INTERMIT, AMB_120) +AMB_ENTRY(65, DIGI_JET1, AMB_INTERMIT, AMB_120) +AMB_ENTRY(66, DIGI_MOTO1, AMB_INTERMIT, AMB_45) +AMB_ENTRY(67, DIGI_MOTO2, AMB_INTERMIT, AMB_60) +AMB_ENTRY(68, DIGI_NEON1, AMB_INTERMIT, AMB_5) +AMB_ENTRY(69, DIGI_SUBWAY, AMB_INTERMIT, AMB_30) +AMB_ENTRY(70, DIGI_TRAIN1, AMB_INTERMIT, AMB_120) +AMB_ENTRY(71, DIGI_BIRDS1, AMB_INTERMIT, AMB_10) +AMB_ENTRY(72, DIGI_BIRDS2, AMB_INTERMIT, AMB_10) +AMB_ENTRY(73, DIGI_AMOEBA, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(74, DIGI_TRAIN3, AMB_INTERMIT, AMB_120) +AMB_ENTRY(75, DIGI_TRAIN8, AMB_INTERMIT, AMB_120) +AMB_ENTRY(76, DIGI_WHIPME, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(77, DIGI_FLAGWAVE, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(78, DIGI_ANIMECRY, AMB_NONE, AMB_NOTICS) +AMB_ENTRY(79, DIGI_WINDCHIMES, AMB_INTERMIT, AMB_10) +AMB_ENTRY(80, DIGI_BOATCREAK, AMB_INTERMIT, AMB_10) +AMB_ENTRY(81, DIGI_SHIPBELL, AMB_INTERMIT, AMB_30) +AMB_ENTRY(82, DIGI_FOGHORN, AMB_INTERMIT, AMB_120) + +#undef AMB_ENTRY diff --git a/polymer/eduke32/source/sw/src/anim.c b/polymer/eduke32/source/sw/src/anim.c new file mode 100644 index 000000000..6187058e3 --- /dev/null +++ b/polymer/eduke32/source/sw/src/anim.c @@ -0,0 +1,385 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" +#include "cache1d.h" + +#include "keys.h" +#include "mytypes.h" +#include "develop.h" +#include "fx_man.h" +#include "music.h" +#include "scriplib.h" +#include "file_lib.h" +#include "gamedefs.h" +#include "keyboard.h" +#include "util_lib.h" + +#include "control.h" +#include "config.h" +#include "sounds.h" +#include "function.h" + +#include "game.h" +#include "colormap.h" +#include "net.h" + +#include "animlib.h" +#include "anim.h" + +#define MAX_ANMS 10 +anim_t *anm_ptr[MAX_ANMS]; + +int ANIMnumframes; +unsigned char ANIMpal[3*256]; +unsigned char ANIMnum = 0; +short SoundState; + +char *ANIMname[] = +{ + "sw.anm", + "swend.anm", + "sumocinm.anm", + "zfcin.anm", +}; + +#define ANIM_TILE(num) (MAXTILES-11 + (num)) + +VOID AnimShareIntro(int frame, int numframes) +{ + int zero=0; + + if (frame == numframes-1) + ototalclock += 120; + else if (frame == 1) + { + PlaySound(DIGI_NOMESSWITHWANG,&zero,&zero,&zero,v3df_none); + ototalclock += 120*3; + } + else + ototalclock += 8; + + if (frame == 5) + { + PlaySound(DIGI_INTRO_SLASH,&zero,&zero,&zero,v3df_none); + } + else if (frame == 15) + { + PlaySound(DIGI_INTRO_WHIRL,&zero,&zero,&zero,v3df_none); + } +} + +VOID AnimSerp(int frame, int numframes) +{ + int zero=0; + ototalclock += 16; + + if (frame == numframes-1) + ototalclock += 1*120; + + if (frame == 1) + { + PlaySound(DIGI_SERPTAUNTWANG,&zero,&zero,&zero,v3df_none); + } + else if (frame == 16) + { + PlaySound(DIGI_SHAREND_TELEPORT,&zero,&zero,&zero,v3df_none); + } + else if (frame == 35) + { + SoundState++; + PlaySound(DIGI_WANGTAUNTSERP1,&zero,&zero,&zero,v3df_none); + } + else if (frame == 51) + { + SoundState++; + PlaySound(DIGI_SHAREND_UGLY1,&zero,&zero,&zero,v3df_none); + } + else if (frame == 64) + { + SoundState++; + PlaySound(DIGI_SHAREND_UGLY2,&zero,&zero,&zero,v3df_none); + } +} + +VOID AnimSumo(int frame, int numframes) +{ + int zero=0; + ototalclock += 10; + + if (frame == numframes-1) + ototalclock += 1*120; + + if (frame == 1) + ototalclock += 30; + + if (frame == 2) + { + // hungry + PlaySound(DIGI_JG41012,&zero,&zero,&zero,v3df_none); + } + else if (frame == 30) + { + PlaySound(DIGI_HOTHEADSWITCH,&zero,&zero,&zero,v3df_none); + } + else if (frame == 42) + { + PlaySound(DIGI_HOTHEADSWITCH,&zero,&zero,&zero,v3df_none); + } + else if (frame == 59) + { + PlaySound(DIGI_JG41028,&zero,&zero,&zero,v3df_none); + } +} + +VOID AnimZilla(int frame, int numframes) +{ + int zero=0; + ototalclock += 16; + + if (frame == numframes-1) + ototalclock += 1*120; + + if (frame == 1) + { + PlaySound(DIGI_ZC1,&zero,&zero,&zero,v3df_none); + } + else if (frame == 5) + { + PlaySound(DIGI_JG94024,&zero,&zero,&zero,v3df_none); + } + else if (frame == 14) + { + PlaySound(DIGI_ZC2,&zero,&zero,&zero,v3df_none); + } + else if (frame == 30) + { + PlaySound(DIGI_ZC3,&zero,&zero,&zero,v3df_none); + } + else if (frame == 32) + { + PlaySound(DIGI_ZC4,&zero,&zero,&zero,v3df_none); + } + else if (frame == 37) + { + PlaySound(DIGI_ZC5,&zero,&zero,&zero,v3df_none); + } + else if (frame == 63) + { + PlaySound(DIGI_Z16043,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC6,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC7,&zero,&zero,&zero,v3df_none); + } + else if (frame == 72) + { + PlaySound(DIGI_ZC7,&zero,&zero,&zero,v3df_none); + } + else if (frame == 73) + { + PlaySound(DIGI_ZC4,&zero,&zero,&zero,v3df_none); + } + else if (frame == 77) + { + PlaySound(DIGI_ZC5,&zero,&zero,&zero,v3df_none); + } + else if (frame == 87) + { + PlaySound(DIGI_ZC8,&zero,&zero,&zero,v3df_none); + } + else if (frame == 103) + { + PlaySound(DIGI_ZC7,&zero,&zero,&zero,v3df_none); + } + else if (frame == 108) + { + PlaySound(DIGI_ZC9,&zero,&zero,&zero,v3df_none); + } + else if (frame == 120) + { + PlaySound(DIGI_JG94039,&zero,&zero,&zero,v3df_none); + } +} + +unsigned char *LoadAnm(short anim_num) +{ + int handle; + int length; + unsigned char *animbuf, *palptr; + int i,j,k; + + DSPRINTF(ds,"LoadAnm"); + MONO_PRINT(ds); + + // this seperate allows the anim to be precached easily + + ANIMnum = anim_num; + + // lock it + walock[ANIM_TILE(ANIMnum)] = 219; + + if (anm_ptr[anim_num] == 0) + { + handle = kopen4load(ANIMname[ANIMnum], 0); + if (handle == -1) + return NULL; + length = kfilelength(handle); + + allocache((void **) &anm_ptr[anim_num], length + sizeof(anim_t), &walock[ANIM_TILE(ANIMnum)]); + animbuf = (unsigned char *)((intptr_t)anm_ptr[anim_num] + sizeof(anim_t)); + + kread(handle, animbuf, length); + kclose(handle); + } + else + { + animbuf = (unsigned char *)((intptr_t)anm_ptr[anim_num] + sizeof(anim_t)); + } + + return animbuf; +} + +void +playanm(short anim_num) +{ + unsigned char *animbuf, *palptr; + int i, j, k, length = 0, numframes = 0; + int32 handle = -1; + unsigned char ANIMvesapal[4*256]; + unsigned char tempbuf[256]; + unsigned char *palook_bak = palookup[0]; + UserInput uinfo = { FALSE, FALSE, dir_None }; + + ANIMnum = anim_num; + + KB_FlushKeyboardQueue(); + KB_ClearKeysDown(); + + DSPRINTF(ds,"PlayAnm"); + MONO_PRINT(ds); + + DSPRINTF(ds,"PlayAnm"); + MONO_PRINT(ds); + + animbuf = LoadAnm(anim_num); + if (!animbuf) + return; + + DSPRINTF(ds,"PlayAnm - Palette Stuff"); + MONO_PRINT(ds); + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + palookup[0] = tempbuf; + + ANIM_LoadAnim(animbuf); + ANIMnumframes = ANIM_NumFrames(); + numframes = ANIMnumframes; + + palptr = ANIM_GetPalette(); + for (i = 0; i < 768; i++) + ANIMvesapal[i] = palptr[i]>>2; + + tilesizx[ANIM_TILE(ANIMnum)] = 200; + tilesizy[ANIM_TILE(ANIMnum)] = 320; + + clearview(0); + + setbrightness(gs.Brightness,ANIMvesapal,2); + if (ANIMnum == 1) + { + // draw the first frame + waloff[ANIM_TILE(ANIMnum)] = (intptr_t)ANIM_DrawFrame(1); + invalidatetile(ANIM_TILE(ANIMnum), 0, 1<<4); + rotatesprite(0 << 16, 0 << 16, 65536L, 512, ANIM_TILE(ANIMnum), 0, 0, 2 + 4 + 8 + 16 + 64, 0, 0, xdim - 1, ydim - 1); + } + + SoundState = 0; + //ototalclock = totalclock + 120*2; + ototalclock = totalclock; + + for (i = 1; i < numframes; i++) + { + while (totalclock < ototalclock) + { + handleevents(); + CONTROL_GetUserInput(&uinfo); + CONTROL_ClearUserInput(&uinfo); + switch (ANIMnum) + { + case ANIM_INTRO: + if (KB_KeyWaiting() || uinfo.button0 || uinfo.button1 || quitevent) + goto ENDOFANIMLOOP; + break; + case ANIM_SERP: + if (KEY_PRESSED(KEYSC_ESC) || uinfo.button1 || quitevent) + goto ENDOFANIMLOOP; + break; + } + + getpackets(); + } + + switch (ANIMnum) + { + case ANIM_INTRO: + AnimShareIntro(i,numframes); + break; + case ANIM_SERP: + AnimSerp(i,numframes); + break; + case ANIM_SUMO: + AnimSumo(i,numframes); + break; + case ANIM_ZILLA: + AnimZilla(i,numframes); + break; + } + + waloff[ANIM_TILE(ANIMnum)] = (intptr_t)ANIM_DrawFrame(i); + invalidatetile(ANIM_TILE(ANIMnum), 0, 1<<4); + + rotatesprite(0 << 16, 0 << 16, 65536L, 512, ANIM_TILE(ANIMnum), 0, 0, 2 + 4 + 8 + 16 + 64, 0, 0, xdim - 1, ydim - 1); + nextpage(); + } + + // pause on final frame + while (totalclock < ototalclock) + { + handleevents(); + getpackets(); + } + +ENDOFANIMLOOP: + + clearview(0); + nextpage(); + palookup[0] = palook_bak; + setbrightness(gs.Brightness, (unsigned char *)palette_data, 2); + + KB_FlushKeyboardQueue(); + KB_ClearKeysDown(); + ANIM_FreeAnim(); + walock[ANIM_TILE(ANIMnum)] = 1; +} diff --git a/polymer/eduke32/source/sw/src/anim.h b/polymer/eduke32/source/sw/src/anim.h new file mode 100644 index 000000000..f51867c19 --- /dev/null +++ b/polymer/eduke32/source/sw/src/anim.h @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#define ANIM_INTRO 0 +#define ANIM_SERP 1 +#define ANIM_SUMO 2 +#define ANIM_ZILLA 3 + +unsigned char *LoadAnm(short anim_num); +void playanm(short anim_num); diff --git a/polymer/eduke32/source/sw/src/bldscript.c b/polymer/eduke32/source/sw/src/bldscript.c new file mode 100644 index 000000000..5afa176be --- /dev/null +++ b/polymer/eduke32/source/sw/src/bldscript.c @@ -0,0 +1,643 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1996, 2005 - 3D Realms Entertainment + +This file is NOT part of Shadow Warrior version 1.2 +However, it is either an older version of a file that is, or is +some test code written during the development of Shadow Warrior. +This file is provided purely for educational interest. + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +// scriplib.c +#include "build.h" +#include "editor.h" +#include "cache1d.h" + +#include "names2.h" +#include "game.h" + +#include "parse.h" + +#define PATHSEPERATOR '\\' + + +//#define COMPUTE_TOTALS 1 + +/* +============================================================================= + + ABNORMAL TERMINATION + +============================================================================= +*/ +void Error(char *error, ...) +{ + va_list argptr; + + va_start(argptr,error); + vprintf(error,argptr); + va_end(argptr); + printf("\n"); + exit(1); +} + + + +/* +============================================================================= + + PARSING STUFF + +============================================================================= +*/ + +char token[MAXTOKEN]; +char *scriptbuffer,*script_p,*scriptend_p; +int grabbed; +int scriptline; +BOOL endofscript; +BOOL tokenready; // only TRUE if UnGetToken was just called + +/* +============== += += LoadScriptFile += +============== +*/ + +BOOL LoadScriptFile(char *filename) +{ + int size, readsize; + int fp; + + + if ((fp=kopen4load(filename,0)) == -1) + { + // If there's no script file, forget it. + return FALSE; + } + + size = kfilelength(fp); + + scriptbuffer = (char *)malloc(size); + + ASSERT(scriptbuffer != NULL); + + readsize = kread(fp, scriptbuffer, size); + + kclose(fp); + + ASSERT(readsize == size); + + + // Convert filebuffer to all upper case + //strupr(scriptbuffer); + + script_p = scriptbuffer; + scriptend_p = script_p + size; + scriptline = 1; + endofscript = FALSE; + tokenready = FALSE; + return TRUE; +} + + +/* +============== += += UnGetToken += += Signals that the current token was not used, and should be reported += for the next GetToken. Note that + +GetToken (TRUE); +UnGetToken (); +GetToken (FALSE); + += could cross a line boundary. += +============== +*/ + +void UnGetToken(void) +{ + tokenready = TRUE; +} + + +/* +============== += += GetToken += +============== +*/ + +void GetToken(BOOL crossline) +{ + char *token_p; + + if (tokenready) // is a token already waiting? + { + tokenready = FALSE; + return; + } + + if (script_p >= scriptend_p) + { + if (!crossline) + Error("Line %i is incomplete\n",scriptline); + endofscript = TRUE; + return; + } + +// +// skip space +// +skipspace: + while (*script_p <= 32) + { + if (script_p >= scriptend_p) + { + if (!crossline) + Error("Line %i is incomplete\n",scriptline); + endofscript = TRUE; + return; + } + if (*script_p++ == '\n') + { + if (!crossline) + Error("Line %i is incomplete\n",scriptline); + scriptline++; + } + } + + if (script_p >= scriptend_p) + { + if (!crossline) + Error("Line %i is incomplete\n",scriptline); + endofscript = TRUE; + return; + } + + if (*script_p == '#') // # is comment field + { + if (!crossline) + Error("Line %i is incomplete\n",scriptline); + while (*script_p++ != '\n') + if (script_p >= scriptend_p) + { + endofscript = TRUE; + return; + } + goto skipspace; + } + +// +// copy token +// + token_p = token; + + while (*script_p > 32 && *script_p != '#') + { + *token_p++ = *script_p++; + if (script_p == scriptend_p) + break; + ASSERT(token_p != &token[MAXTOKEN]); +// Error ("Token too large on line %i\n",scriptline); + } + + *token_p = 0; +} + + +/* +============== += += TokenAvailable += += Returns true if there is another token on the line += +============== +*/ + +BOOL TokenAvailable(void) +{ + char *search_p; + + search_p = script_p; + + if (search_p >= scriptend_p) + return FALSE; + + while (*search_p <= 32) + { + if (*search_p == '\n') + return FALSE; + search_p++; + if (search_p == scriptend_p) + return FALSE; + + } + + if (*search_p == '#') + return FALSE; + + return TRUE; +} + +void DefaultExtension(char *path, char *extension) +{ + char *src; +// +// if path doesn't have a .EXT, append extension +// (extension should include the .) +// + src = path + strlen(path) - 1; + + while (*src != '\\' && src != path) + { + if (*src == '.') + return; // it has an extension + src--; + } + + strcat(path, extension); +} + + +void DefaultPath(char *path, char *basepath) +{ + char temp[128]; + + if (path[0] == '\\') + return; // absolute path location + strcpy(temp,path); + strcpy(path,basepath); + strcat(path,temp); +} + + +void StripFilename(char *path) +{ + int length; + + length = strlen(path)-1; + while (length > 0 && path[length] != PATHSEPERATOR) + length--; + path[length] = 0; +} + + +void ExtractFileBase(char *path, char *dest) +{ + char *src; + int length; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && *(src-1) != '\\') + src--; + +// +// copy up to eight characters +// + memset(dest,0,8); + length = 0; + while (*src && *src != '.') + { + if (++length == 9) + Error("Filename base of %s >8 chars",path); + *dest++ = toupper(*src++); + } +} + + +/* +============== += += ParseNum / ParseHex += +============== +*/ + +int ParseHex(char *hex) +{ + char *str; + int num; + + num = 0; + str = hex; + + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str-'0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str-'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str-'A'; + else + Error("Bad hex number: %s",hex); + str++; + } + + return num; +} + + +int ParseNum(char *str) +{ + if (str[0] == '$') + return ParseHex(str+1); + if (str[0] == '0' && str[1] == 'x') + return ParseHex(str+2); + return atol(str); +} + + + + +// voxelarray format is: +// spritenumber, voxelnumber +int aVoxelArray[MAXTILES]; + +extern int nextvoxid; + +// Load all the voxel files using swvoxfil.txt script file +// Script file format: + +// # - Comment +// spritenumber (in artfile), voxel number, filename +// Ex. 1803 0 medkit2.kvx +// 1804 1 shotgun.kvx +// etc.... + +void LoadKVXFromScript(char *filename) +{ + int lNumber=0,lTile=0; // lNumber is the voxel no. and lTile is the editart tile being + // replaced. + char *sName; // KVS file being loaded in. + + int grabbed=0; // Number of lines parsed + + sName = (char *)malloc(256); // Up to 256 bytes for path + ASSERT(sName != NULL); + + // zero out the array memory with -1's for pics not being voxelized + memset(aVoxelArray,-1,sizeof(aVoxelArray)); + + // Load the file + if (!LoadScriptFile(filename)) return; + + do + { + GetToken(TRUE); // Crossing a line boundary on the end of line to first token + // of a new line is permitted (and expected) + if (endofscript) + break; + + lTile = atol(token); + + GetToken(FALSE); + lNumber = atol(token); + + GetToken(FALSE); + strcpy(sName,token); // Copy the whole token as a file name and path + + // Load the voxel file into memory + if (!qloadkvx(lNumber,sName)) + { + // Store the sprite and voxel numbers for later use + aVoxelArray[lTile] = lNumber; // Voxel num + } + + if (lNumber >= nextvoxid) // JBF: so voxels in the def file append to the list + nextvoxid = lNumber + 1; + + grabbed++; + ASSERT(grabbed < MAXSPRITES); + + } + while (script_p < scriptend_p); + + free(scriptbuffer); + script_p = NULL; +} + + +/// MISC //////////////////////////////////////////////////////////////////// + +/* +extern int idleclock,slackerclock; + +// Watch dog function. Tracks user's work times. +void LogUserTime( BOOL bIsLoggingIn ) +{ + int size, readsize; + time_t time_of_day; + char serialid[20],filename[100],fbase[20],buf[26],filetemp[100]; + FILE *fp; + int tothours, totmins, totsecs, gtotalclock=0,gidleclock=0; + ldiv_t mins_secs; + ldiv_t hrs_mins; + int i; + + char path[] = "o:\\user\\jimn\\logs\\"; +// char path[] = "c:\\jim\\sw\\"; + + memset(filename,0,sizeof(filename)); + memset(fbase,0,sizeof(fbase)); + memset(serialid,0,sizeof(serialid)); + memset(buf,0,sizeof(buf)); + memset(filetemp,0,sizeof(filetemp)); + + // Get the time of day user logged in to build + time_of_day = time( NULL ); + + // Get the serial number from the user's disk drive "it's unique!" + system("dir > serid.bld"); + LoadScriptFile("serid.bld"); + + // Go to the serial number + for (i=0; i<11; i++) + { + GetToken (TRUE); + if (endofscript) + return; + } + + // Copy the token to serialid + strcpy(serialid,token); + + // Free the script memory when done + free(scriptbuffer); + script_p = NULL; + + // Build a file name using serial id. + strcpy(filename,path); + strncpy(fbase,serialid,8); + strcat(fbase,".bld"); + strcat(filename,fbase); + + // Delete the temp file + system("erase serid.bld"); + + // Unhide the file so it can be opened + _dos_setfileattr(filename,_A_NORMAL); + + + // Open the file + fp = fopen( filename, "a+" ); + + // Opening on the network failed, try putting it on the current disk drive + if(fp == NULL) + { + // Unhide the file so it can be opened/this works if file was created before! + _dos_setfileattr(fbase,_A_NORMAL); + fp = fopen( fbase, "a+" ); + strcpy(filetemp,fbase); + } else + strcpy(filetemp,filename); + + + if( fp == NULL) + return; + else + { + if(bIsLoggingIn) + { + fprintf(fp, "//////////////////////////////\n"); + fprintf(fp, "User logged into build at: %s", _ctime( &time_of_day, buf ) ); + }else + { + totsecs = totalclock/120; // Convert totalclock to seconds. + + mins_secs = ldiv( totsecs, 60L ); + totmins = mins_secs.quot; + totsecs = mins_secs.rem; + + hrs_mins = ldiv( totmins, 60L); + tothours = hrs_mins.quot; + totmins = hrs_mins.rem; + + fprintf(fp, "TotalClock: %ld\n",totalclock); +#ifdef COMPUTE_TOTALS + fprintf(fp, "IdleClock: %ld\n",slackerclock); +#endif + fprintf(fp, "Time this session: %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs); +#ifdef COMPUTE_TOTALS + totsecs = (totalclock-slackerclock)/120; // Convert totalclock to seconds. + if(totsecs<=0) totsecs = 0; + + mins_secs = ldiv( totsecs, 60L ); + totmins = mins_secs.quot; + totsecs = mins_secs.rem; + + hrs_mins = ldiv( totmins, 60L); + tothours = hrs_mins.quot; + totmins = hrs_mins.rem; + fprintf(fp, "Time - idleclock : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs); +#endif + } + + fclose( fp ); + } + +#if 1 + if(!bIsLoggingIn) + { + // Compute total time for file + LoadScriptFile(filetemp); + + do { + GetToken (TRUE); + + if (endofscript) + break; + + if(!strcmpi(token,"totalclock:")) + { + GetToken(TRUE); + gtotalclock += atol(token); + } +#if 0 + if(!strcmpi(token,"idleclock:")) + { + GetToken(TRUE); + gidleclock += atol(token); + } +#endif + + } while (script_p < scriptend_p); + + // Free the script memory when done + free(scriptbuffer); + script_p = NULL; + + // Open the file + fp = fopen( filetemp, "a+" ); + + // Now compute the grand total + if(fp != NULL) + { + totsecs = gtotalclock/120; // Convert totalclock to seconds. + + mins_secs = ldiv( totsecs, 60L ); + totmins = mins_secs.quot; + totsecs = mins_secs.rem; + + hrs_mins = ldiv( totmins, 60L); + tothours = hrs_mins.quot; + totmins = hrs_mins.rem; + + fprintf(fp, "\nTotal time so far : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs); + +#if 0 + totsecs = (gtotalclock-gidleclock)/120; // Convert totalclock to seconds. + if(totsecs<=0) totsecs = 0; + + mins_secs = ldiv( totsecs, 60L ); + totmins = mins_secs.quot; + totsecs = mins_secs.rem; + + hrs_mins = ldiv( totmins, 60L); + tothours = hrs_mins.quot; + totmins = hrs_mins.rem; + + fprintf(fp, "\nTotal actual time : %ld Hours %ld Mins %ld Secs\n",tothours,totmins,totsecs); +#endif + + fclose(fp); + } + } +#endif + + _dos_setfileattr(filename,_A_HIDDEN); + + +} +*/ diff --git a/polymer/eduke32/source/sw/src/border.c b/polymer/eduke32/source/sw/src/border.c new file mode 100644 index 000000000..54a938fcb --- /dev/null +++ b/polymer/eduke32/source/sw/src/border.c @@ -0,0 +1,585 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "lists.h" +#include "game.h" +#include "common_game.h" +#include "net.h" +#include "text.h" + +#define BAR_HEIGHT 48 +#define XDIM 320 +#define YDIM 200 + +short DebugBorderShade = 0; + +short RegBorderTest[] = +{ + 51, 53, 127, 128, 140, 145, 152, 197, 198, 201, 205, 206, 213, 218, 242, 243, + 245, 246, 247, 257, 2560, 2561, 2562, 2570, 2571, 2572, 2573, 2576, 2578, + 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2593, 2594 +}; +short SWBorderTest[] = +{ + 51, 53, 127, 128, 140, 145, 201, 205, 206, 213, 218, + 245, 2560, 2573, 2576, 2580, 2581, 2582, 2583, 2584, 2593 +}; + +#undef BORDER_TILE +#define BORDER_TILE \ + (isShareware ? \ + SWBorderTest[gs.BorderTile % SIZ(SWBorderTest)] : \ + RegBorderTest[gs.BorderTile % SIZ(RegBorderTest)] \ + ) + +#define f_320 FIXED(320,0) +#define f_200 FIXED(200,0) + +#define X_TO_FIXED(val) (x_aspect_mul*(val)) +#define Y_TO_FIXED(val) (y_aspect_mul*(val)) + +BOOL RedrawScreen = FALSE; + +int f_xdim, f_ydim, x_pix_size, y_pix_size, x_aspect_mul, y_aspect_mul; +int CrosshairX, CrosshairY; + +extern BOOL BorderAdjust; +BOOL GlobSpriteBoxUpdateEveryFrame = FALSE; + +PANEL_SPRITEp +pSpawnFullScreenSpriteBox(PLAYERp pp, short id, short pic, short pri, int x, int y, short x1, short y1, short x2, short y2) +{ + PANEL_SPRITEp psp; + extern BOOL DrawBeforeView; + + psp = pSpawnSprite(pp, NULL, pri, x, y); + + psp->ID = id; + psp->numpages = numpages; + if (GlobSpriteBoxUpdateEveryFrame) + { + psp->numpages = 1; + } + psp->picndx = -1; + psp->picnum = pic; + psp->x1 = x1; + psp->y1 = y1; + psp->x2 = x2; + psp->y2 = y2; + psp->shade = DebugBorderShade; + + //SET(psp->flags, PANF_STATUS_AREA | PANF_KILL_AFTER_SHOW | PANF_IGNORE_START_MOST | PANF_DRAW_BEFORE_VIEW | PANF_NOT_ALL_PAGES); + SET(psp->flags, PANF_STATUS_AREA | PANF_KILL_AFTER_SHOW | PANF_IGNORE_START_MOST | PANF_DRAW_BEFORE_VIEW); + //DrawBeforeView = TRUE; + + //SET(psp->flags, PANF_SCREEN_CLIP | PANF_KILL_AFTER_SHOW | PANF_IGNORE_START_MOST); + + return psp; +} + +VOID SetCrosshair(VOID) +{ + int wdx,wdy,x,y; + + wdx = ((windowx2-windowx1)/2); + wdy = ((windowy2-windowy1)/2); + x = windowx1 + wdx; + y = windowy1 + wdy; + + CrosshairX = x / (xdim/320.0); + CrosshairY = y / (ydim/200.0); + + // rotatesprite takes FIXED point number + CrosshairX <<= 16; + CrosshairY <<= 16; +} + + +VOID +SetupAspectRatio(VOID) +{ + f_xdim = FIXED(xdim, 0); + f_ydim = FIXED(ydim, 0); + + x_pix_size = (f_320 / xdim); + y_pix_size = (f_200 / ydim); + + x_aspect_mul = (f_xdim / 320); + y_aspect_mul = (f_ydim / 200); +} + +VOID +SetConsoleDmost(VOID) +{ + int ystart; + int xstart; + + int i; + int adj=0; + + // dont setup the startumost/dmost arrays if border is 0 + if (gs.BorderNum == BORDER_NONE || gs.BorderNum == BORDER_MINI_BAR) + return; + + // + // Set the whole thing to the size of the bar + // + + ystart = f_ydim - Y_TO_FIXED(BAR_HEIGHT); + + if (ydim == 480 && gs.BorderNum == 2) + adj = 1; + + //for (i = FIXED(0, 0); i < f_320; i += x_pix_size) + for (i = 0; i < xdim; i++) + // define picture + // boundaries + { + startdmost[i] = MSW(ystart) + adj; + } +} + +VOID ClearStartMost(VOID) +{ + int i; + + for (i = 0; i < xdim; i++) + startdmost[i] = ydim; + + memset(startumost, 0, sizeof(startumost)); +} + +VOID +SetFragBar(PLAYERp pp) +{ + short i, num_frag_bars; + int y; + extern SHORT OrigCommPlayers; + + if (numplayers <= 1) + return; + + if (gNet.MultiGameType == MULTI_GAME_COOPERATIVE) + return; + + // if player sprite has not been initialized we have no business + // sticking a frag bar up. Prevents processing from MenuLevel etc. + if (!pp->SpriteP) + return; + + //num_frag_bars = ((numplayers-1)/4)+1; + num_frag_bars = ((OrigCommPlayers-1)/4)+1; + + for (i = windowx1; i <= windowx2; i++) + { + y = (tilesizy[FRAG_BAR] * num_frag_bars) - (2 * (num_frag_bars-1)); + y = y * (ydim/200.0); + + if (windowy1 < y) + startumost[i] = y; + } + + for (i = 0, y = 0; i < num_frag_bars; i++) + { + pSpawnFullScreenSprite(pp, FRAG_BAR, PRI_MID, 0, y); + y += tilesizy[FRAG_BAR] - 2; + } + + // write each persons kill info to everybody + // for (i = 0; i < numplayers; i++) + TRAVERSE_CONNECT(i) + { + PlayerUpdateKills(Player + i, 0); + DisplayFragNames(Player + i); + } +} + +BOOL RectOverlap(short tx1, short ty1, short bx1, short by1, short tx2, short ty2, short bx2, short by2) +{ + if (bx1 >= tx2) + if (tx1 <= bx2) + if (ty1 <= by2) + if (by1 >= ty2) + return TRUE; + + return FALSE; +} + +VOID DrawBorderShade(PLAYERp pp, short shade_num, short wx1, short wy1, short wx2, short wy2) +{ + short i,j,k,l; + PANEL_SPRITEp psp; + int dark_shade = 27 - (shade_num * 6); + int light_shade = 20 - (shade_num * 6); + + for (i = 0; i < xdim; i += tilesizx[BORDER_TILE]) + { + for (j = 0; j < ydim; j += tilesizy[BORDER_TILE]) + { + k = i + tilesizx[BORDER_TILE]; + l = j + tilesizy[BORDER_TILE]; + + if (RectOverlap(i, j, k, l, wx1 - 1, wy1 - 1, wx2 + 1, wy1)) + { + // draw top box of the border + psp = pSpawnFullScreenSpriteBox(pp, ID_BORDER_TOP, BORDER_TILE, PRI_BACK + 1, i, j, wx1 - 1, wy1 - 1, wx2 + 1, wy1); + psp->shade = dark_shade; + psp->ID = ID_BORDER_SHADE; + } + + if (RectOverlap(i, j, k, l, wx1 - 1, wy2, wx2 + 1, wy2 + 1)) + { + // draw bottom box of the border + psp = pSpawnFullScreenSpriteBox(pp, ID_BORDER_BOTTOM, BORDER_TILE, PRI_BACK + 1, i, j, wx1 - 1, wy2, wx2 + 1, wy2 + 1); + psp->shade = light_shade; + psp->ID = ID_BORDER_SHADE; + } + if (RectOverlap(i, j, k, l, wx1 - 1, wy1 - 1, wx1, wy2 + 1)) + { + // draw left box of the border + psp = pSpawnFullScreenSpriteBox(pp, ID_BORDER_LEFT, BORDER_TILE, PRI_BACK + 1, i, j, wx1 - 1, wy1 - 1, wx1, wy2 + 1); + psp->shade = dark_shade; + psp->ID = ID_BORDER_SHADE; + } + if (RectOverlap(i, j, k, l, wx2, wy1 - 1, wx2 + 1, wy2 + 1)) + { + // draw right box of the border + psp = pSpawnFullScreenSpriteBox(pp, ID_BORDER_RIGHT, BORDER_TILE, PRI_BACK + 1, i, j, wx2, wy1 - 1, wx2 + 1, wy2 + 1); + psp->shade = light_shade; + psp->ID = ID_BORDER_SHADE; + } + } + } +} + +VOID +BorderShade(PLAYERp pp, BOOL refresh) +{ + int i, j, k, l, wx1, wx2, wy1, wy2; + PANEL_SPRITEp psp; + BYTE lines; + + wx1 = windowx1 - 1; + wy1 = windowy1 - 1; + wx2 = windowx2 + 1; + wy2 = windowy2 + 1; + + for (lines = 0; lines < 4; lines++) + { + + // make sure that these values dont go out of bound - which they do + wx1 = max(wx1, 0); + wx2 = min(wx2, xdim - 1); + wy1 = max(wy1, 0); + + if (refresh) + { + // silly thing seems off by 1 + wy2 = min(wy2, ydim - (Y_TO_FIXED(BAR_HEIGHT) >> 16) - 2); + } + else + { + if (gs.BorderNum >= BORDER_BAR+1 && gs.BorderNum <= BORDER_BAR+2) + wy2 = min(wy2, ydim - 1); + else + wy2 = min(wy2, ydim - (Y_TO_FIXED(BAR_HEIGHT) >> 16) - 1); + } + + DrawBorderShade(pp, lines, wx1, wy1, wx2, wy2); + // increase view size by one - dont do a set view though + wx1--; + wy1--; + wx2++; + wy2++; + } +} + + +BORDER_INFO BorderInfoValues[] = +{ + // x,y,screensize + {0, 0, 0}, + {0, 0, 0}, + {0, BAR_HEIGHT, 0}, + + {0, BAR_HEIGHT, (1 * 16)}, + {0, BAR_HEIGHT, (2 * 16)}, + {0, BAR_HEIGHT, (3 * 16)}, + {0, BAR_HEIGHT, (4 * 16)}, + {0, BAR_HEIGHT, (5 * 16)}, + {0, BAR_HEIGHT, (6 * 16)}, + {0, BAR_HEIGHT, (7 * 16)}, + {0, BAR_HEIGHT, (8 * 16)}, + {0, BAR_HEIGHT, (9 * 16)}, + {0, BAR_HEIGHT, (10 * 16)}, + {0, BAR_HEIGHT, (11 * 16)}, + {0, BAR_HEIGHT, (12 * 16)} +}; + + +VOID DrawBorder(PLAYERp pp, short x, short y, short x2, short y2) +{ + short i,j,k,l; + short count = 0; + + for (i = 0; i < xdim; i += tilesizx[BORDER_TILE]) + { + for (j = 0; j < ydim; j += tilesizy[BORDER_TILE]) + { + k = i + tilesizx[BORDER_TILE]; + l = j + tilesizy[BORDER_TILE]; + + if (RectOverlap(i, j, k, l, x, y, windowx1-1, y2)) + { + // draw top box of the border + pSpawnFullScreenSpriteBox(pp, ID_BORDER_TOP, BORDER_TILE, PRI_BACK, i, j, x, y, windowx1-1, y2); + count++; + } + + if (RectOverlap(i, j, k, l, windowx2+1, y, x2, y2)) + { + // draw bottom box of the border + pSpawnFullScreenSpriteBox(pp, ID_BORDER_BOTTOM, BORDER_TILE, PRI_BACK, i, j, windowx2+1, y, x2, y2); + count++; + } + + if (RectOverlap(i, j, k, l, windowx1, y, windowx2, windowy1-1)) + { + // draw left box of the border + pSpawnFullScreenSpriteBox(pp, ID_BORDER_LEFT, BORDER_TILE, PRI_BACK, i, j, windowx1, y, windowx2, windowy1-1); + count++; + } + + if (RectOverlap(i, j, k, l, windowx1, windowy2+1, windowx2, y2)) + { + // draw right box of the border + pSpawnFullScreenSpriteBox(pp, ID_BORDER_RIGHT, BORDER_TILE, PRI_BACK, i, j, windowx1, windowy2+1, windowx2, y2); + count++; + } + } + } +} + +VOID DrawPanelBorderSides(PLAYERp pp, short x, short y, short x2, short y2, short panl, short panr) +{ + short i,j,k,l; + short count = 0; + + for (i = 0; i < xdim; i += tilesizx[BORDER_TILE]) + { + for (j = 0; j < ydim; j += tilesizy[BORDER_TILE]) + { + k = i + tilesizx[BORDER_TILE]; + l = j + tilesizy[BORDER_TILE]; + + if (RectOverlap(i, j, k, l, x, y, panl, y2)) + { + pSpawnFullScreenSpriteBox(pp, ID_PANEL_BORDER_LEFT, BORDER_TILE, PRI_BACK, i, j, x, y, panl, y2); + count++; + } + + if (RectOverlap(i, j, k, l, panr, y, x2, y2)) + { + pSpawnFullScreenSpriteBox(pp, ID_PANEL_BORDER_RIGHT, BORDER_TILE, PRI_BACK, i, j, panr, y, x2, y2); + count++; + } + } + } +} + +static +VOID BorderSetView(PLAYERp UNUSED(pp), int *Xdim, int *Ydim, int *ScreenSize) +{ + void setview(int scrx1, int scry1, int scrx2, int scry2); + int x, x2, y, y2; + BORDER_INFO *b; + + BorderInfo = BorderInfoValues[gs.BorderNum]; + + b = &BorderInfo; + + // figure out the viewing window x and y dimensions + *Xdim = MSW(f_xdim - X_TO_FIXED(b->Xdim)); + *Ydim = MSW(f_ydim - Y_TO_FIXED(b->Ydim)); + *ScreenSize = MSW(f_xdim - X_TO_FIXED(b->ScreenSize)); + + // figure out the viewing window x and y coordinates + x = DIV2(*Xdim) - DIV2(*ScreenSize); + x2 = x + *ScreenSize - 1; + y = DIV2(*Ydim) - DIV2((*ScreenSize **Ydim) / *Xdim); + y2 = y + ((*ScreenSize **Ydim) / *Xdim) - 1; + + if (ydim == 480 && gs.BorderNum == 2) + { + y2+=2; + } + + // global windowx1, windowx2, windowy1, windowy2 coords set here + setview(x, y, x2, y2); + SetCrosshair(); +} + +// +// Redraw the border without changing the view +// + +static VOID +BorderRefresh(PLAYERp pp) +{ + int i, j; + int x, x2, y, y2; + BORDER_INFO *b; + + if (pp != Player + myconnectindex) + return; + + if (!BorderAdjust) + return; + + if (gs.BorderNum < BORDER_BAR) + return; + + // Redraw the BORDER_TILE only if getting smaller + BorderInfo = BorderInfoValues[gs.BorderNum]; + + b = &BorderInfo; + + // A refresh does not change the view size so we dont need to do a + // setview + // We don't need the calculations for the border drawing boxes - its + // the whole screen + // minus the border if necessary + + // fill in the sides of the panel when the screen is wide + if (gs.BorderNum >= BORDER_BAR && widescreen) + { + int sidew = (xdim - scale(320, ydim, mulscale16(200, pixelaspect))) / 2; + + x = 0; + x2 = xdim - 1; + + y = ydim - (Y_TO_FIXED(b->Ydim) >> 16); + y2 = ydim - 1; + + DrawPanelBorderSides(pp, x, y, x2, y2, sidew, xdim-sidew); + } + + // only need a border if border is > BORDER_BAR + if (gs.BorderNum > BORDER_BAR) + { + // make sure that these values dont go out of bound - which they do + x = 0; + x2 = xdim - 1; + + y = 0; + y2 = ydim - (Y_TO_FIXED(b->Ydim) >> 16) - 1; + + DrawBorder(pp, x, y, x2, y2); + + // kill ALL outstanding (not yet drawn) border shade sprites before + // doing more shading + pKillScreenSpiteIDs(pp, ID_BORDER_SHADE); + + BorderShade(pp, TRUE); + } +} + +// +// Redraw the whole screen +// + +VOID SetBorder(PLAYERp pp, int value) +{ + int diff; + int Xdim, Ydim, ScreenSize; + BOOL set_view = TRUE; + + if (pp != Player + myconnectindex) + return; + + if (!BorderAdjust) + return; + + if (value >= 0) // just refresh + gs.BorderNum = value; + + if (gs.BorderNum < BORDER_NONE) + { + gs.BorderNum = BORDER_NONE; + //return; + } + + if (gs.BorderNum > (int)SIZ(BorderInfoValues) - 1) + { + gs.BorderNum = SIZ(BorderInfoValues) - 1; + return; + } + + BorderSetView(pp, &Xdim, &Ydim, &ScreenSize); + + if (gs.BorderNum >= BORDER_BAR) + { + BorderRefresh(pp); + + if (gs.BorderNum == BORDER_BAR) + SetConsoleDmost(); + + pSpawnFullScreenSprite(pp, STATUS_BAR, PRI_FRONT, 0, 200 - tilesizy[STATUS_BAR]); + PlayerUpdatePanelInfo(Player + screenpeek); + } + + SetFragBar(pp); +} + +VOID +SetRedrawScreen(PLAYERp pp) +{ + int i, j; + //int x, x2, y, y2; + BORDER_INFO *b; + + if (pp != Player + myconnectindex) + return; + + if (!BorderAdjust) + return; + + if (gs.BorderNum < BORDER_NONE) + gs.BorderNum = BORDER_NONE; + + // Redraw the BORDER_TILE only if getting smaller + BorderInfo = BorderInfoValues[gs.BorderNum]; + + b = &BorderInfo; + + // test at redrawing the whole screen + RedrawScreen = TRUE; +} + diff --git a/polymer/eduke32/source/sw/src/bots.h b/polymer/eduke32/source/sw/src/bots.h new file mode 100644 index 000000000..58565e0eb --- /dev/null +++ b/polymer/eduke32/source/sw/src/bots.h @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +// BOTS.H +// Contains useful header information for bot creation + +#ifndef BOTS_H +#define BOTS_H + + +// BOT DEFINITIONS AND STRUCTURES + +typedef enum +{ + BOTstand, BOThide, BOTrun, BOTduck, BOTjump, BOTstrafe, BOTshoot, BOTuseinv, + BOTopen, BOTswimup, BOTswimdown, BOTturn, BOTuserts +} BOT_Actions; + +// Linked lists containing node trees that are chosen based on desired actions +struct NODEstruct; +typedef struct NODEstruct NODE, *NODEp; + +struct NODEstruct +{ + NODEp p, l, r; // Pointers to tree nodes + int goalx, goaly, goalz; // x,y,z point bot wants to get to + BOT_Actions action; // Action to take if this node is reached + int tics; // Optionally stay in this node for x tics. +}; + +struct NODETREEstruct; +typedef struct NODETREEstruct NODETREE, *NODETREEp; + +struct NODETREEstruct +{ + short SpriteNum; // Sprite number in sprite array of goal item + NODEp tree; // This is the node tree used to navigate to goal + BOOL Locked; // If list is locked, a bot is using/modifying it and + // other bots cannot modify it while it's locked +}; + +// Bots main action variables +typedef struct BOT_BRAIN +{ + short tgt_inv; // Inventory item it wants to use + short tgt_weapon; // Weapon in wants to activate and use + short tgt_enemy; // Enemy it wants to kill + short tgt_sprite; // Sprite it wants to pickup or operate + short tgt_sector; // Sector it wants to get to + short tgt_wall; // Wall it wants to touch + BOT_Actions action; // Bot's current action +} BotBrain, *BotBrain_p; + +// NOTE: +// The following arrays should be saved off with save games! + +// 0 = Item not accessible, no item of type was found +// 1 = Shuriken +// 3 = Caltrops +// 4 = Gas Bomb +// 5 = Flash Bomb +// 6 = Uzi Ammo +// 7 = Shotgun Ammo +// 8 = Rocket Ammo +// 9 = 40mm Ammo +// 10 = Sticky Bombs +// 11 = Rail Ammo +// 12 = Head Ammo +// 13 = Heart Ammo +// 14 = Uzi +// 15 = Shotgun +// 16 = Rocket Launcher +// 17 = 40mm Launcher +// 18 = Rail Gun +// 19 = Head +// 20 = Heart +// 21 = MedKit +// 22 = Armor +// 23 = Big Armor +// 24 = Portable MedKit +// 25 = Fortune Cookie +//////////////////////// +extern NODETREE BOT_TREELIST[25][50]; // There can be up to 50 of each item +// with a cooresponding search tree for each + +#endif diff --git a/polymer/eduke32/source/sw/src/break.c b/polymer/eduke32/source/sw/src/break.c new file mode 100644 index 000000000..61b08ae27 --- /dev/null +++ b/polymer/eduke32/source/sw/src/break.c @@ -0,0 +1,1140 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "tags.h" +#include "sprite.h" +#include "sector.h" +#include "light.h" +#include "weapon.h" + +#include "break.h" + +BREAK_INFOp GlobBreakInfo; + +static int SectorOfWall(short theline); +static void DoWallBreakSpriteMatch(short match); + +BREAK_INFO WallBreakInfo[] = +{ + { 60, -1, SHRAP_METAL, BF_KILL, 0 }, + { 82, -1, SHRAP_METAL, BF_KILL, 0 }, + { 1, 3593, SHRAP_METAL, 0, 0 }, +//{ 13, -1, SHRAP_PAPER }, +//{ 14, -1, SHRAP_PAPER }, +//{ 49, -1, SHRAP_PAPER }, +//{ 52, -1, SHRAP_PAPER }, +//{ 99, -1, SHRAP_PAPER }, +//{ 102, -1, SHRAP_PAPER }, +//{ 207, -1, SHRAP_PAPER }, + { 253, 255, SHRAP_GLASS, 0, 0 }, + { 254, 255, SHRAP_GLASS, 0, 0 }, + { 282, -1, SHRAP_GLASS, 0, 0 }, + { 283, 4974, SHRAP_METAL, 0, 0 }, + { 318, 599, SHRAP_GLASS, 0, 0}, + { 486, -1, SHRAP_METAL, 0, 0 }, + { 487, 3676, SHRAP_METAL, 0, 0 }, + { 628, 3585, SHRAP_METAL, 0, 0}, + { 630, 3586, SHRAP_METAL, 0, 0}, + { 633, 608, SHRAP_GLASS, 0, 0}, + { 634, 608, SHRAP_GLASS, 0, 0 }, + { 637, 3587, SHRAP_METAL, 0, 0}, + { 640, 3588, SHRAP_METAL, 0, 0}, + { 641, 3588, SHRAP_METAL, 0, 0}, + { 665, 3588, SHRAP_METAL, 0, 0}, + { 742, 3589, SHRAP_COIN, 0, 0}, + { 743, 3590, SHRAP_COIN, 0, 0}, + { 750, 608, SHRAP_GLASS, 0, 0}, + { 2667, 608, SHRAP_GLASS, 0, 0}, + { 2769, 3681, SHRAP_GLASS, 0, 0}, + { 2676, 3591, SHRAP_GLASS, 0, 0}, + { 2677, 3592, SHRAP_GLASS, 0, 0}, + { 2687, 2727, SHRAP_GLASS, 0, 0}, + { 2688, 2728, SHRAP_GLASS, 0, 0}, +//{ 2714, 3593, SHRAP_GLASS}, + { 2732, 3594, SHRAP_GLASS, 0, 0}, + { 2777, 3683, SHRAP_METAL, 0, 0}, + { 2778, 2757, SHRAP_GLASS, 0, 0}, + { 2801, 3591, SHRAP_GLASS, 0, 0}, + { 2804, 3595, SHRAP_GLASS, 0, 0}, + { 2807, 3596, SHRAP_GLASS, 0, 0}, + { 2810, 4989, SHRAP_METAL, 0, 0}, + { 4890, 4910, SHRAP_METAL, 0, 0}, + { 4891, 4911, SHRAP_METAL, 0, 0}, + { 4892, 4912, SHRAP_METAL, 0, 0}, + { 4893, 4913, SHRAP_METAL, 0, 0}, + { 4894, 4914, SHRAP_METAL, 0, 0}, + { 4895, 4915, SHRAP_METAL, 0, 0}, + { 3336, 4940, SHRAP_COIN, 0, 0}, + { 3337, 4941, SHRAP_COIN, 0, 0}, + { 4885, 4888, SHRAP_METAL, 0, 0}, + { 4887, 4889, SHRAP_COIN, 0, 0}, + { 3350, 4942, SHRAP_GLASS, 0, 0}, + { 3351, 4943, SHRAP_METAL, 0, 0}, + { 3352, 4944, SHRAP_METAL, 0, 0}, + { 3353, 4945, SHRAP_METAL, 0, 0}, + { 4896, 4898, SHRAP_METAL, 0, 0}, + { 4897, 4899, SHRAP_METAL, 0, 0}, + { 3385, 4981, SHRAP_METALMIX, 0, 0}, + { 3389, 4982, SHRAP_METALMIX, 0, 0}, + { 3393, 4984, SHRAP_METALMIX, 0, 0}, + { 3397, 4983, SHRAP_METALMIX, 0, 0}, + { 3401, 4985, SHRAP_METALMIX, 0, 0}, + { 3405, 4986, SHRAP_METALMIX, 0, 0}, + { 3409, 4988, SHRAP_METALMIX, 0, 0}, + { 3413, 4987, SHRAP_METALMIX, 0, 0}, + { 253, 255, SHRAP_METALMIX, 0, 0}, + { 283, 4974, SHRAP_METALMIX, 0, 0}, + { 299, 4975, SHRAP_METALMIX, 0, 0}, + {5078, 5079, SHRAP_METALMIX, 0, 0}, + {5080, 5092, SHRAP_MARBELS, 0, 0}, + {5083, 5093, SHRAP_MARBELS, 0, 0}, + {5086, 5094, SHRAP_MARBELS, 0, 0}, + {5089, 5095, SHRAP_MARBELS, 0, 0}, + {4970, 4973, SHRAP_METAL, 0, 0}, + {297, 4980, SHRAP_METAL, 0, 0}, + {1, 4976, SHRAP_METAL, 0, 0}, + {4917, 4918, SHRAP_METAL, 0, 0}, + {4902, 4903, SHRAP_METAL, 0, 0}, +}; + +BREAK_INFO SpriteBreakInfo[] = +{ + { 60, -1, SHRAP_METAL, BF_KILL, 0}, + { 82, -1, SHRAP_METAL, BF_KILL, 0}, + { 138, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 253, 255, SHRAP_GLASS, 0, 0}, + { 254, 255, SHRAP_GLASS, 0, 0}, + { 270, -1, SHRAP_PAPER, BF_BURN, 0}, + { 271, -1, SHRAP_PAPER, BF_BURN, 0}, + { 272, -1, SHRAP_WOOD, 0, 0}, + { 274, -1, SHRAP_PAPER, BF_BURN, 0}, +//{ 276, -1, SHRAP_WOOD }, +//{ 277, -1, SHRAP_WOOD }, +//{ 278, -1, SHRAP_WOOD }, + { 282, -1, SHRAP_GLASS, 0, 0}, + { 283, -1, SHRAP_METAL, 0, 0}, + { 297, -1, SHRAP_METAL, 0, 0}, + { 299, -1, SHRAP_METAL, 0, 0}, + { 363, -1, SHRAP_METAL, BF_KILL, 0}, + { 365, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 366, -1, SHRAP_METAL, BF_KILL,5}, + { 367, -1, SHRAP_WOOD, BF_KILL, 0}, + { 368, -1, SHRAP_GIBS, BF_KILL, 0}, + { 369, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 371, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 372, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 374, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 375, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 376, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 377, -1, SHRAP_STONE, BF_KILL, 0}, + { 379, -1, SHRAP_WOOD, BF_KILL, 0}, + { 380, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 385, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 386, -1, SHRAP_GIBS, BF_KILL, 0}, + { 387, -1, SHRAP_GIBS, BF_KILL, 0}, + { 388, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 391, -1, SHRAP_GIBS, BF_KILL, 0}, + { 392, -1, SHRAP_GIBS, BF_KILL, 0}, + { 393, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 394, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 395, -1, SHRAP_GIBS, BF_KILL, 0}, + { 396, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 397, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 398, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 399, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 400, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 401, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 402, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 407, -1, SHRAP_METAL, BF_KILL, 0}, + { 408, -1, SHRAP_PAPER, BF_BURN, 0}, + { 409, -1, SHRAP_PAPER, BF_BURN, 0}, + { 415, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL,5}, + { 418, -1, SHRAP_GENERIC, BF_KILL|BF_FIRE_FALL,5}, + { 422, -1, SHRAP_METAL, BF_KILL, 0}, + { 423, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 424, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 425, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 428, -1, SHRAP_METAL, BF_BURN, 0}, + { 430, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 431, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 432, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 433, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 434, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 435, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 436, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 437, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 438, -1, SHRAP_GIBS, BF_KILL, 0}, + { 441, -1, SHRAP_WOOD, BF_KILL, 0}, + { 442, -1, SHRAP_STONE, BF_KILL, 0}, + { 443, -1, SHRAP_STONE, BF_KILL|BF_FIRE_FALL, 0}, + { 453, -1, SHRAP_WOOD, BF_KILL, 0}, + { 458, -1, SHRAP_STONE, BF_KILL, 0}, + { 459, -1, SHRAP_STONE, BF_KILL, 0}, + { 460, -1, SHRAP_METAL, BF_KILL, 0}, + { 461, -1, SHRAP_METAL, BF_KILL, 0}, + { 462, -1, SHRAP_METAL, BF_KILL, 0}, + { 463, -1, SHRAP_STONE, BF_KILL, 0}, + { 467, -1, SHRAP_STONE, BF_KILL, 0}, + { 468, -1, SHRAP_WOOD, BF_KILL, 0}, + { 475, -1, SHRAP_GLASS, BF_KILL, 0}, + { 481, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 482, -1, SHRAP_WOOD, BF_KILL, 0}, + { 483, -1, SHRAP_WOOD, BF_KILL|BF_TOUGH, 0}, + { 491, -1, SHRAP_WOOD, BF_KILL, 0}, + { 492, -1, SHRAP_METAL, BF_KILL, 0}, + { 493, -1, SHRAP_METAL, BF_KILL, 0}, + { 498, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 500, -1, SHRAP_METAL, BF_KILL, 0}, + { 501, -1, SHRAP_METAL, BF_KILL, 0}, + { 504, -1, SHRAP_METAL, BF_KILL,5}, + { 505, -1, SHRAP_BLOOD, BF_KILL,5}, + { 506, -1, SHRAP_GENERIC, BF_KILL,5}, + { 507, -1, SHRAP_GLASS, BF_KILL, 0}, + { 508, -1, SHRAP_GLASS, BF_KILL, 0}, + { 509, -1, SHRAP_GLASS, BF_KILL, 0}, + { 510, -1, SHRAP_GLASS, BF_KILL, 0}, + { 511, -1, SHRAP_METAL, BF_KILL, 0}, + { 512, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL,5}, + { 516, -1, SHRAP_WOOD, BF_BURN, 0}, + { 517, -1, SHRAP_WOOD, BF_BURN, 0}, + { 518, -1, SHRAP_WOOD, BF_BURN, 0}, + { 519, -1, SHRAP_WOOD, BF_FIRE_FALL|BF_KILL,5}, + { 520, -1, SHRAP_WOOD, BF_KILL, 0}, + { 521, -1, SHRAP_WOOD, BF_KILL|BF_FIRE_FALL, 0}, + { 537, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 541, -1, SHRAP_WOOD, BF_KILL|BF_FIRE_FALL, 0}, + { 586, -1, SHRAP_METAL, BF_KILL, 0}, + { 590, -1, SHRAP_METAL, BF_KILL, 0}, + { 591, -1, SHRAP_METAL, BF_KILL, 0}, + { 593, 608, SHRAP_GLASS,BF_TOUGH, 0}, + { 604, -1, SHRAP_METAL, BF_KILL, 0}, + { 613, -1, SHRAP_LARGE_EXPLOSION, BF_KILL, 0}, + { 614, -1, SHRAP_METAL, BF_KILL, 0}, + { 615, -1, SHRAP_METAL, BF_KILL, 0}, + { 618, -1, SHRAP_GLASS, BF_KILL, 0}, + { 646, -1, SHRAP_METAL, BF_KILL, 0}, + { 647, -1, SHRAP_LARGE_EXPLOSION, BF_KILL, 0}, + { 648, -1, SHRAP_LARGE_EXPLOSION, BF_KILL, 0}, + { 649, -1, SHRAP_METAL, BF_KILL, 0}, + { 656, -1, SHRAP_METAL, BF_KILL, 0}, + { 657, -1, SHRAP_METAL, BF_KILL, 0}, + { 658, -1, SHRAP_LARGE_EXPLOSION, BF_KILL, 0}, + { 659, -1, SHRAP_METAL, BF_KILL,5}, +//{ 660, -1, SHRAP_STONE, BF_TOUGH|BF_KILL}, +//{ 661, -1, SHRAP_STONE, BF_TOUGH|BF_KILL}, +//{ 662, -1, SHRAP_STONE, BF_TOUGH|BF_KILL}, + { 663, -1, SHRAP_METAL, BF_KILL,10}, + { 664, -1, SHRAP_METAL, BF_KILL,5}, + { 666, -1, SHRAP_PLANT, BF_KILL, 0}, + { 670, -1, SHRAP_METAL, BF_KILL|BF_FIRE_FALL, 0}, + { 671, -1, SHRAP_GLASS, BF_KILL|BF_FIRE_FALL, 0}, + { 673, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 674, -1, SHRAP_GIBS, BF_KILL, 0}, + { 675, -1, SHRAP_GIBS, BF_KILL, 0}, + { 676, -1, SHRAP_GIBS, BF_KILL, 0}, + { 678, -1, SHRAP_GLASS, BF_KILL,5}, + { 679, -1, SHRAP_GLASS, BF_KILL,5}, + { 683, -1, SHRAP_GLASS, BF_KILL,5}, + { 684, -1, SHRAP_GLASS, BF_KILL,5}, + { 685, -1, SHRAP_GLASS, BF_KILL,5}, + { 686, -1, SHRAP_PAPER, BF_KILL,5}, + { 687, -1, SHRAP_STONE, BF_KILL|BF_TOUGH, 0}, + { 688, -1, SHRAP_STONE, BF_KILL|BF_TOUGH, 0}, + { 690, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 692, -1, SHRAP_WOOD, BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 695, -1, SHRAP_STONE, BF_KILL, 0}, + { 696, -1, SHRAP_STONE, BF_KILL, 0}, + { 697, -1, SHRAP_STONE, BF_KILL, 0}, + { 698, -1, SHRAP_STONE, BF_KILL, 0}, + { 699, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 702, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 703, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 704, -1, SHRAP_STONE, BF_TOUGH|BF_KILL, 0}, + { 706, -1, SHRAP_PLANT, BF_KILL, 0}, + { 707, -1, SHRAP_PLANT, BF_KILL, 0}, + { 710, -1, SHRAP_PLANT, BF_KILL, 0}, + { 711, -1, SHRAP_PLANT, BF_KILL, 0}, + { 714, -1, SHRAP_STONE, BF_KILL,5}, + { 721, -1, SHRAP_GIBS, BF_KILL, 0}, + { 722, -1, SHRAP_GIBS, BF_KILL, 0}, + { 723, -1, SHRAP_GIBS, BF_KILL, 0}, + { 724, -1, SHRAP_GIBS, BF_KILL, 0}, + { 725, -1, SHRAP_PLANT, BF_KILL, 0}, + { 730, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 744, -1, SHRAP_GLASS, BF_KILL,5}, + { 2563, -1, SHRAP_PAPER, BF_BURN, 0}, + { 2564, -1, SHRAP_PAPER, BF_BURN, 0}, + { 3570, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN, 0}, + { 3571, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 3572, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 3573, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 3574, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 3575, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 3576, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 3577, -1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 3578, -1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 3579, -1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 3580, -1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 3581, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN, 0}, + { 3582, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN, 0}, + { 2640, -1, SHRAP_STONE, BF_KILL,5}, + { 2641, -1, SHRAP_STONE, BF_KILL, 0}, + { 2642, -1, SHRAP_STONE, BF_KILL, 0}, + { 2680, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 2681, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 2682, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 2683, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 2684, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 2685, -1, SHRAP_GENERIC, BF_KILL, 0}, + { 2687, 2727, SHRAP_GLASS, 0, 0}, + { 2688, 2728, SHRAP_GLASS, 0, 0}, + { 2699, -1, SHRAP_WOOD, BF_KILL, 0}, + { 2709, -1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 2720, -1, SHRAP_GIBS, BF_KILL, 0}, + { 2721, -1, SHRAP_GIBS, BF_KILL, 0}, + { 2722, -1, SHRAP_GIBS, BF_KILL, 0}, + { 2723, -1, SHRAP_GIBS, BF_KILL, 0}, + { 2724, -1, SHRAP_GIBS, BF_KILL, 0}, + { 2725, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 2726, -1, SHRAP_BLOOD, BF_KILL, 0}, + { 2719, -1, SHRAP_GLASS, BF_KILL, 0}, + { 2750, -1, SHRAP_WOOD, BF_KILL, 0}, + { 2676, 3591, SHRAP_GLASS, 0, 0}, + { 2769, 3681, SHRAP_GLASS, 0, 0}, + { 2777, 3683, SHRAP_METAL, BF_TOUGH, 0}, + { 2778, 2757, SHRAP_GLASS, 0, 0}, + { 3448, 3451, SHRAP_METAL, BF_TOUGH|BF_KILL, 0}, + { 3449, -1, SHRAP_PAPER, BF_KILL, 0}, + { 3497, -1, SHRAP_GENERIC, BF_KILL|BF_TOUGH, 0}, + { 3551, -1, SHRAP_METAL, BF_KILL, 0}, + { 3552, -1, SHRAP_METAL, BF_KILL, 0}, + { 3553, -1, SHRAP_METAL, BF_KILL, 0}, + { 3554, -1, SHRAP_METAL, BF_KILL, 0}, + { 3555, -1, SHRAP_METAL, BF_KILL, 0}, + { 3556, -1, SHRAP_METAL, BF_KILL, 0}, + { 3557, -1, SHRAP_METAL, BF_KILL, 0}, + { 3558, -1, SHRAP_WOOD, BF_KILL, 0}, + { 3568, -1, SHRAP_WOOD, BF_BURN, 0}, + { 4994, -1, SHRAP_METAL, BF_KILL, 0}, + { 4995, -1, SHRAP_METAL, BF_KILL, 0}, + { 5010, -1, SHRAP_WOOD, BF_TOUGH|BF_BURN|BF_OVERRIDE_BLOCK, 0}, + { 5017, -1, SHRAP_PAPER, BF_KILL, 0}, + { 5018, -1, SHRAP_PAPER, BF_KILL, 0}, + { 5019, -1, SHRAP_PAPER, BF_KILL, 0}, + { 5060, -1, SHRAP_METAL, BF_KILL, 0}, + { 5061, -1, SHRAP_METAL, BF_KILL, 0}, + { 5073, -1, SHRAP_GIBS, BF_KILL, 0}, + +// Evil ninja Hari-Kari - can gib + { 4218, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + +// old ninja dead frames + { 1133, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 1134, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + +// dead actors + { 811, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 1440, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 1512, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 1643, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 1680, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + + { 4219+7, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 4236, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, // Evil Ninja cut in half + { 4421, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, // Dead Big Ripper + { 4312, -1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, // Dead Coolie Ghost + { 766, -1, SHRAP_COIN,BF_KILL, 0}, + { 767, -1, SHRAP_COIN,BF_KILL, 0}, + { 2700, -1, SHRAP_PAPER,BF_KILL, 0}, + { 2701, -1, SHRAP_PAPER,BF_KILL, 0}, + { 2702, -1, SHRAP_PAPER,BF_KILL, 0}, + { 2703, -1, SHRAP_PAPER,BF_KILL, 0}, + { 2704, -1, SHRAP_PAPER,BF_KILL, 0}, + { 2705, -1, SHRAP_PAPER,BF_KILL, 0}, + { 2218, -1, SHRAP_METAL,BF_KILL, 0}, // Caltrops are breakable + { 689, -1, SHRAP_METAL,BF_TOUGH|BF_KILL, 0}, +//{ 2540, -1, SHRAP_METAL,BF_TOUGH|BF_KILL}, + { 3354, -1, SHRAP_METAL,BF_KILL, 0}, + { 3357, -1, SHRAP_PAPER,BF_KILL, 0}, + { 4886, -1, SHRAP_GLASS,BF_KILL, 0}, + { 646, 708, SHRAP_METAL,BF_TOUGH|BF_KILL, 0}, + { 708, -1, SHRAP_METAL,BF_TOUGH|BF_KILL, 0}, + { 656, -1, SHRAP_METAL,BF_KILL, 0}, + { 663, -1, SHRAP_METAL,BF_KILL, 0}, + { 664, -1, SHRAP_METAL,BF_KILL, 0}, + { 691, -1, SHRAP_METAL,BF_KILL, 0}, + { 5021,-1, SHRAP_GIBS, BF_KILL, 0}, + { 712, -1, SHRAP_LARGE_EXPLOSION, BF_KILL, 0}, + { 713, -1, SHRAP_LARGE_EXPLOSION, BF_KILL, 0}, + { 693, -1, SHRAP_WOODMIX, BF_KILL|BF_TOUGH, 0}, + { 5041,-1, SHRAP_GIBS, BF_KILL, 0}, + { 5042,5077,SHRAP_GIBS, BF_TOUGH|BF_KILL, 0}, + { 5077,-1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 3356,3358,SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 3358,-1, SHRAP_WOOD, BF_TOUGH|BF_KILL, 0}, + { 900, -1, SHRAP_GIBS, BF_KILL, 0}, + { 901, -1, SHRAP_GIBS, BF_KILL, 0}, + { 902, -1, SHRAP_GIBS, BF_KILL, 0}, + { 915, -1, SHRAP_GIBS, BF_KILL, 0}, + { 916, -1, SHRAP_GIBS, BF_KILL, 0}, + { 917, -1, SHRAP_GIBS, BF_KILL, 0}, + { 930, -1, SHRAP_GIBS, BF_KILL, 0}, + { 931, -1, SHRAP_GIBS, BF_KILL, 0}, + { 932, -1, SHRAP_GIBS, BF_KILL, 0}, + { 1670,-1, SHRAP_GIBS, BF_KILL, 0}, + { 2219,-1, SHRAP_METAL,BF_KILL|BF_TOUGH, 0}, + { 4768,-1, SHRAP_GLASS,BF_KILL, 0}, + { 4792,-1, SHRAP_GLASS,BF_KILL, 0}, + { 4816,-1, SHRAP_GLASS,BF_KILL, 0}, + { 4840,-1, SHRAP_GLASS,BF_KILL, 0}, + { 4584,-1, SHRAP_GIBS, BF_KILL, 0}, + { 5062,-1, SHRAP_WOOD, BF_KILL|BF_TOUGH, 0}, + { 5063,4947,SHRAP_PAPERMIX, BF_KILL|BF_TOUGH|BF_LEAVE_BREAK, 0}, + { 4947,-1, SHRAP_PAPERMIX, BF_KILL|BF_TOUGH, 0}, + { 1160,-1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, + { 5104,-1, SHRAP_GIBS, BF_KILL, 0}, + { 3795,-1, SHRAP_GIBS, BF_KILL, 0}, + { 470,-1, SHRAP_GIBS, BF_KILL, 0}, + { 5205,-1, SHRAP_GIBS, BF_KILL|BF_TOUGH, 0}, +//{ 969,-1, SHRAP_GIBS, BF_KILL|BF_TOUGH}, +//{ 1277,-1, SHRAP_GIBS, BF_KILL|BF_TOUGH}, +}; + +////////////////////////////////////////////// +// SORT & SEARCH SUPPORT +////////////////////////////////////////////// + +int CompareBreakInfo(BREAK_INFOp break_info1, BREAK_INFOp break_info2) +{ + // will return a number less than 0 if break_info1 < break_info2 + return break_info1->picnum - break_info2->picnum; +} + +int CompareSearchBreakInfo(short *picnum, BREAK_INFOp break_info) +{ + // will return a number less than 0 if picnum < break_info->picnum + return *picnum - break_info->picnum; +} + +BREAK_INFOp FindWallBreakInfo(short picnum) +{ + return bsearch(&picnum, &WallBreakInfo, SIZ(WallBreakInfo), sizeof(BREAK_INFO), (int(*)(const void *,const void *))CompareSearchBreakInfo); +} + +BREAK_INFOp FindSpriteBreakInfo(short picnum) +{ + return bsearch(&picnum, &SpriteBreakInfo, SIZ(SpriteBreakInfo), sizeof(BREAK_INFO), (int(*)(const void *,const void *))CompareSearchBreakInfo); +} + +////////////////////////////////////////////// +// SETUP +////////////////////////////////////////////// + +void SortBreakInfo(void) +{ + qsort(&SpriteBreakInfo, SIZ(SpriteBreakInfo), sizeof(BREAK_INFO), (int(*)(const void *,const void *))CompareBreakInfo); + qsort(&WallBreakInfo, SIZ(WallBreakInfo), sizeof(BREAK_INFO), (int(*)(const void *,const void *))CompareBreakInfo); +} + +BREAK_INFOp SetupWallForBreak(WALLp wallp) +{ + BREAK_INFOp break_info; + + break_info = FindWallBreakInfo(wallp->picnum); + if (break_info) + { + wallp->lotag = TAG_WALL_BREAK; + SET(wallp->extra, WALLFX_DONT_STICK); + + // set for cacheing + if (break_info->breaknum >= 0) + SET_GOTPIC(break_info->breaknum); + } + + if (wallp->overpicnum > 0 && TEST(wallp->cstat, CSTAT_WALL_MASKED)) + { + break_info = FindWallBreakInfo(wallp->overpicnum); + if (break_info) + { + wallp->lotag = TAG_WALL_BREAK; + SET(wallp->extra, WALLFX_DONT_STICK); + } + } + + return break_info; +} + +BREAK_INFOp SetupSpriteForBreak(SPRITEp sp) +{ + short picnum = sp->picnum; + BREAK_INFOp break_info; + + // ignore as a breakable if true + if (sp->lotag == TAG_SPRITE_HIT_MATCH) + return NULL; + + break_info = FindSpriteBreakInfo(picnum); + if (break_info) + { + + // use certain sprites own blocking for determination + if (TEST(break_info->flags, BF_OVERRIDE_BLOCK)) + { + // if not blocking then skip this code + if (!TEST(sp->cstat, CSTAT_SPRITE_BLOCK)) + { + return (BREAK_INFOp)(-1); + } + } + + if (TEST(break_info->flags, BF_BURN)) + SET(sp->extra, SPRX_BURNABLE); + else + SET(sp->extra, SPRX_BREAKABLE); + + sp->clipdist = SPRITEp_SIZE_X(sp); + + SET(sp->cstat, CSTAT_SPRITE_BREAKABLE); + + // set for cacheing + if (break_info->breaknum >= 0) + SET_GOTPIC(break_info->breaknum); + } + + return break_info; +} + +////////////////////////////////////////////// +// ACTIVATE +////////////////////////////////////////////// + +short FindBreakSpriteMatch(short match) +{ + short i,nexti; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_BREAKABLE], i, nexti) + { + if (SPRITE_TAG2(i) == match && sprite[i].picnum == ST1) + { + return i; + } + } + + return -1; +} + +// +// WALL +// + +int AutoBreakWall(WALLp wallp, int hitx, int hity, int hitz, short ang, short type) +{ + BREAK_INFOp break_info; + short BreakSprite; + WALLp nwp; + SPRITEp bsp; + + //DSPRINTF(ds,"wallnum %d, pic %d, lo %d, hi %d",wallp-wall, wallp->picnum, wallp->lotag, wallp->hitag); + MONO_PRINT(ds); + + wallp->lotag = 0; + if (wallp->nextwall >= 0) + { + nwp = &wall[wallp->nextwall]; + + // get rid of both sides + // only break ONE of the walls + + if (nwp->lotag == TAG_WALL_BREAK && + nwp->overpicnum > 0 && + TEST(nwp->cstat, CSTAT_WALL_MASKED)) + { + nwp->lotag = 0; + } + } + + if (wallp->overpicnum > 0 && TEST(wallp->cstat, CSTAT_WALL_MASKED)) + break_info = FindWallBreakInfo(wallp->overpicnum); + else + break_info = FindWallBreakInfo(wallp->picnum); + + if (!break_info) + { + //DSPRINTF(ds,"Break Info not found - wall %d", wallp - wall); + MONO_PRINT(ds); + + return FALSE; + } + + // Check to see if it should break with current weapon type + if (!CheckBreakToughness(break_info, type)) return FALSE; + + if (hitx != MAXLONG) + { + // need correct location for spawning shrap + BreakSprite = COVERinsertsprite(0, STAT_DEFAULT); + ASSERT(BreakSprite >= 0); + bsp = &sprite[BreakSprite]; + bsp->cstat = 0; + bsp->extra = 0; + bsp->ang = ang; + bsp->picnum = ST1; + bsp->xrepeat = bsp->yrepeat = 64; + setspritez(BreakSprite, hitx, hity, hitz); + + // pass Break Info Globally + GlobBreakInfo = break_info; + SpawnShrap(BreakSprite, -1); + GlobBreakInfo = NULL; + + KillSprite(BreakSprite); + } + + // change the wall + if (wallp->overpicnum > 0 && TEST(wallp->cstat, CSTAT_WALL_MASKED)) + { + if (break_info->breaknum == -1) + { + RESET(wallp->cstat, CSTAT_WALL_MASKED|CSTAT_WALL_1WAY|CSTAT_WALL_BLOCK_HITSCAN|CSTAT_WALL_BLOCK); + wallp->overpicnum = 0; + if (wallp->nextwall >= 0) + { + nwp = &wall[wallp->nextwall]; + RESET(nwp->cstat, CSTAT_WALL_MASKED|CSTAT_WALL_1WAY|CSTAT_WALL_BLOCK_HITSCAN|CSTAT_WALL_BLOCK); + nwp->overpicnum = 0; + } + } + else + { + RESET(wallp->cstat, CSTAT_WALL_BLOCK_HITSCAN|CSTAT_WALL_BLOCK); + wallp->overpicnum = break_info->breaknum; + if (wallp->nextwall >= 0) + { + nwp = &wall[wallp->nextwall]; + RESET(nwp->cstat, CSTAT_WALL_BLOCK_HITSCAN|CSTAT_WALL_BLOCK); + nwp->overpicnum = break_info->breaknum; + } + } + } + else + { + if (break_info->breaknum == -1) + wallp->picnum = 594; // temporary break pic + else + { + wallp->picnum = break_info->breaknum; + if (wallp->hitag < 0) + DoWallBreakSpriteMatch(wallp->hitag); + } + } + + + return TRUE; +} + +BOOL UserBreakWall(WALLp wp, short UNUSED(ang)) +{ + short SpriteNum; + SPRITEp sp; + short match = wp->hitag; + int block_flags = CSTAT_WALL_BLOCK|CSTAT_WALL_BLOCK_HITSCAN; + int type_flags = CSTAT_WALL_TRANSLUCENT|CSTAT_WALL_MASKED|CSTAT_WALL_1WAY; + int flags = block_flags|type_flags; + short ret = FALSE; + + SpriteNum = FindBreakSpriteMatch(match); + + if (SpriteNum < 0) + { + // do it the old way and get rid of wall - assumed to be masked + DoSpawnSpotsForKill(match); + RESET(wp->cstat, flags); + if (wp->nextwall >= 0) + RESET(wall[wp->nextwall].cstat, flags); + + // clear tags + wp->hitag = wp->lotag = 0; + if (wp->nextwall >= 0) + wall[wp->nextwall].hitag = wall[wp->nextwall].lotag = 0; + return TRUE; + } + + sp = &sprite[SpriteNum]; + + if (wp->picnum == SP_TAG5(sp)) + return TRUE; + + // make it BROKEN + if (SP_TAG7(sp) <= 1) + { + DoSpawnSpotsForKill(match); + DoLightingMatch(match, -1); + + if (SP_TAG8(sp) == 0) + { + wp->picnum = SP_TAG5(sp); + // clear tags + wp->hitag = wp->lotag = 0; + if (wp->nextwall >= 0) + wall[wp->nextwall].hitag = wall[wp->nextwall].lotag = 0; + ret = FALSE; + } + else if (SP_TAG8(sp) == 1) + { + // clear flags + RESET(wp->cstat, flags); + if (wp->nextwall >= 0) + RESET(wall[wp->nextwall].cstat, flags); + // clear tags + wp->hitag = wp->lotag = 0; + if (wp->nextwall >= 0) + wall[wp->nextwall].hitag = wall[wp->nextwall].lotag = 0; + + ret = TRUE; + } + else if (SP_TAG8(sp) == 2) + { + // set to broken pic + wp->picnum = SP_TAG5(sp); + + // clear flags + RESET(wp->cstat, block_flags); + if (wp->nextwall >= 0) + RESET(wall[wp->nextwall].cstat, block_flags); + + // clear tags + wp->hitag = wp->lotag = 0; + if (wp->nextwall >= 0) + wall[wp->nextwall].hitag = wall[wp->nextwall].lotag = 0; + + ret = FALSE; + } + + return ret; + } + else + { + // increment picnum + wp->picnum++; + + DoSpawnSpotsForDamage(match); + } + + return FALSE; +} + +int WallBreakPosition(short hitwall, short *sectnum, int *x, int *y, int *z, short *ang) +{ + short w,nw; + WALLp wp; + int nx,ny; + short wall_ang; + int ret=0; + + w = hitwall; + wp = &wall[w]; + + nw = wall[w].point2; + wall_ang = NORM_ANGLE(getangle(wall[nw].x - wall[w].x, wall[nw].y - wall[w].y)+512); + + *sectnum = SectorOfWall(w); + ASSERT(*sectnum >= 0); + + // midpoint of wall + *x = DIV2(wall[w].x + wall[w].x); + *y = DIV2(wall[w].y + wall[w].y); + + //getzsofsector(*sectnum, *x, *y, cz, fz); + + if (wp->nextwall < 0) + { + // white wall + *z = DIV2(sector[*sectnum].floorz + sector[*sectnum].ceilingz); + } + else + { + short next_sectnum = wp->nextsector; + + // red wall + ASSERT(wp->nextsector >= 0); + + // floor and ceiling meet + if (sector[next_sectnum].floorz == sector[next_sectnum].ceilingz) + *z = DIV2(sector[*sectnum].floorz + sector[*sectnum].ceilingz); + else + // floor is above other sector + if (sector[next_sectnum].floorz < sector[*sectnum].floorz) + *z = DIV2(sector[next_sectnum].floorz + sector[*sectnum].floorz); + else + // ceiling is below other sector + if (sector[next_sectnum].ceilingz > sector[*sectnum].ceilingz) + *z = DIV2(sector[next_sectnum].ceilingz + sector[*sectnum].ceilingz); + } + + *ang = wall_ang; + + nx = MOVEx(128, wall_ang); + ny = MOVEy(128, wall_ang); + + *x += nx; + *y += ny; + + updatesectorz(*x,*y,*z,sectnum); + if (*sectnum < 0) + { + *x = MAXLONG; // don't spawn shrap, just change wall + return FALSE; + } + + return TRUE; +} + +// If the tough parameter is not set, then it can't break tough walls and sprites +BOOL HitBreakWall(WALLp wp, int hitx, int hity, int hitz, short ang, short type) +{ + short SpriteNum; + short match = wp->hitag; + + if (match > 0) + { + UserBreakWall(wp, ang); + return TRUE; + } + + //if (hitx == MAXLONG) + { + short sectnum; + WallBreakPosition(wp - wall, §num, &hitx, &hity, &hitz, &ang); + } + + AutoBreakWall(wp, hitx, hity, hitz, ang, type); + return TRUE; +} + +// +// SPRITE +// + +int KillBreakSprite(short BreakSprite) +{ + SPRITEp bp = &sprite[BreakSprite]; + USERp bu = User[BreakSprite]; + short i; + + // Does not actually kill the sprite so it will be valid for the rest + // of the loop traversal. + + // IMPORTANT: Do not change the statnum if possible so that NEXTI in + // SpriteControl loop traversals will maintain integrity. + + SpriteQueueDelete(BreakSprite); + + if (bu) + { + if (bp->statnum == STAT_DEFAULT) + // special case allow kill of sprites on STAT_DEFAULT list + // a few things have users and are not StateControlled + KillSprite(BreakSprite); + else + SetSuicide(BreakSprite); + } + else + { + change_sprite_stat(BreakSprite, STAT_SUICIDE); + } + + return 0; +} + + +int UserBreakSprite(short BreakSprite) +{ + SPRITEp sp; + SPRITEp bp = &sprite[BreakSprite]; + short match = bp->lotag; + short match_extra; + short SpriteNum; + + SpriteNum = FindBreakSpriteMatch(match); + + if (SpriteNum < 0) + { + // even if you didn't find a matching ST1 go ahead and kill it and match everything + // its better than forcing everyone to have a ST1 + DoMatchEverything(NULL, match, -1); + // Kill sound if one is attached + DeleteNoSoundOwner(BreakSprite); + //change_sprite_stat(BreakSprite, STAT_SUICIDE); + KillBreakSprite(BreakSprite); + return TRUE; + } + + sp = &sprite[SpriteNum]; + match_extra = SP_TAG6(bp); + + if (bp->picnum == SP_TAG5(sp)) + return TRUE; + + // make it BROKEN + if (SP_TAG7(sp) <= 1) + { + DoMatchEverything(NULL, match_extra, -1); + //DoSpawnSpotsForKill(match_extra); + DoLightingMatch(match_extra, OFF); + + if (SP_TAG8(sp) == 0) + { + bp->picnum = SP_TAG5(sp); + RESET(bp->extra, SPRX_BREAKABLE); + } + else + // kill sprite + if (SP_TAG8(sp) == 1) + { + // Kill sound if one is attached + DeleteNoSoundOwner(BreakSprite); + KillBreakSprite(BreakSprite); + //KillSprite(BreakSprite); + //change_sprite_stat(BreakSprite, STAT_SUICIDE); + return TRUE; + } + else if (SP_TAG8(sp) == 2) + // leave it + { + // set to broken pic + bp->picnum = SP_TAG5(sp); + + // reset + if (SP_TAG8(sp) == 2) + { + RESET(bp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + } + + RESET(bp->extra, SPRX_BREAKABLE); + } + } + else + { + // increment picnum + bp->picnum++; + + DoSpawnSpotsForDamage(match_extra); + } + + return FALSE; +} + +int AutoBreakSprite(short BreakSprite, short type) +{ + SPRITEp bp = &sprite[BreakSprite]; + BREAK_INFOp break_info; + extern void DoWallBreakMatch(short match); + int SpawnBreakFlames(SHORT SpriteNum); + + break_info = FindSpriteBreakInfo(bp->picnum); + + + if (bp->hitag < 0) + DoWallBreakMatch(bp->hitag); + + if (!break_info) + { + //DSPRINTF(ds,"Break Info not found - sprite %d", bp - sprite); + MONO_PRINT(ds); + return FALSE; + } + + // Check to see if it should break with current weapon type + if (!CheckBreakToughness(break_info, type)) + { + if (break_info->breaknum != -1) + { + if (!TEST(break_info->flags, BF_LEAVE_BREAK)) + { + RESET(bp->extra, SPRX_BREAKABLE); + RESET(bp->cstat, CSTAT_SPRITE_BREAKABLE); + } + + bp->picnum = break_info->breaknum; + // pass Break Info Globally + GlobBreakInfo = break_info; + SpawnShrap(BreakSprite, -1); + GlobBreakInfo = NULL; + if (bp->picnum == 3683) + RESET(bp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + } + + return FALSE; + } + + RESET(bp->extra, SPRX_BREAKABLE); + RESET(bp->cstat, CSTAT_SPRITE_BREAKABLE); + + // pass Break Info Globally + GlobBreakInfo = break_info; + SpawnShrap(BreakSprite, -1); + GlobBreakInfo = NULL; + + // kill it or change the pic + if (TEST(break_info->flags, BF_KILL) || break_info->breaknum == -1) + { + if (TEST(break_info->flags, BF_FIRE_FALL)) + SpawnBreakFlames(BreakSprite); + + RESET(bp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + SET(bp->cstat, CSTAT_SPRITE_INVISIBLE); + // Kill sound if one is attached + DeleteNoSoundOwner(BreakSprite); + KillBreakSprite(BreakSprite); + //change_sprite_stat(BreakSprite, STAT_SUICIDE); + //KillSprite(BreakSprite); + return TRUE; + } + else + { + bp->picnum = break_info->breaknum; + if (bp->picnum == 3683) + RESET(bp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + } + + return FALSE; +} + +BOOL NullActor(USERp u) +{ + // a Null Actor is defined as an actor that has no real controlling programming attached + + // check to see if attached to SO + if (TEST(u->Flags, SPR_SO_ATTACHED)) + return TRUE; + + // does not have a STATE or FUNC to control it + if (!u->State) + return TRUE; + + // does not have a STATE or FUNC to control it + if (!u->ActorActionFunc) + return TRUE; + + return FALSE; +} + +int HitBreakSprite(short BreakSprite, short type) +{ + SPRITEp sp; + SPRITEp bp = &sprite[BreakSprite]; + USERp bu = User[BreakSprite]; + short match = bp->lotag; + short match_extra; + short SpriteNum; + BREAK_INFOp break_info; + + // ignore as a breakable if true + //if (sp->lotag == TAG_SPRITE_HIT_MATCH) + // return(FALSE); + + if (TEST_BOOL1(bp)) + { + if (TEST_BOOL2(bp)) + return FALSE; + + return UserBreakSprite(BreakSprite); + } + + if (bu && !NullActor(bu)) + { + // programmed animating type - without BOOL1 set + if (bp->lotag) + DoLightingMatch(bp->lotag, -1); + + SpawnShrap(BreakSprite, -1); + RESET(bp->extra, SPRX_BREAKABLE); + return FALSE; + } + + return AutoBreakSprite(BreakSprite,type); +} + +static int SectorOfWall(short theline) +{ + short i, startwall, endwall, sectnum; + + sectnum = -1; + + for (i=0; i= startwall) && (theline <= endwall)) + { + sectnum = i; + break; + } + } + + return sectnum; +} + +void DoWallBreakMatch(short match) +{ + short i,sectnum; + int x,y,z; + WALLp wp; + short nw,wall_ang; + + for (i=0; i<=numwalls; i++) + { + if (wall[i].hitag == match) + { + WallBreakPosition(i, §num, &x, &y, &z, &wall_ang); + //nw = wall[i].point2; + //wall_ang = NORM_ANGLE(getangle(wall[nw].x - wall[i].x, wall[nw].y - wall[i].y)+512); + wp = &wall[i]; + wp->hitag = 0; // Reset the hitag + AutoBreakWall(wp, x, y, z, wall_ang, 0); + } + } +} + +static void DoWallBreakSpriteMatch(short match) +{ + short i,nexti; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti) + { + SPRITEp sp = &sprite[i]; + + if (sp->hitag == match) + { + KillSprite(i); + } + } +} diff --git a/polymer/eduke32/source/sw/src/break.h b/polymer/eduke32/source/sw/src/break.h new file mode 100644 index 000000000..5eed346f8 --- /dev/null +++ b/polymer/eduke32/source/sw/src/break.h @@ -0,0 +1,55 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifndef BREAK_PUBLIC_ +#define BREAK_PUBLIC_ + +#define BF_TOUGH (BIT(0)) +#define BF_KILL (BIT(1)) +#define BF_BURN (BIT(2)) +#define BF_OVERRIDE_BLOCK (BIT(3)) +#define BF_FIRE_FALL (BIT(4)) +#define BF_LEAVE_BREAK (BIT(5)) + +typedef struct +{ + short picnum, breaknum, shrap_type; + short flags, shrap_amt; +} BREAK_INFO, *BREAK_INFOp; + +BREAK_INFOp FindWallBreakInfo(short picnum); +BREAK_INFOp FindSpriteBreakInfo(short picnum); +void SortBreakInfo(void); +BREAK_INFOp SetupWallForBreak(WALLp wallp); +BREAK_INFOp SetupSpriteForBreak(SPRITEp sp); +short FindBreakSpriteMatch(short match); +BOOL HitBreakWall(WALLp wp, int, int, int, short ang, short type); +int HitBreakSprite(short BreakSprite, short type); +BOOL CheckBreakToughness(BREAK_INFOp break_info, short ID); +int WallBreakPosition(short hitwall, short *sectnum, int *x, int *y, int *z, short *ang); +void SortBreakInfo(void); + +#endif diff --git a/polymer/eduke32/source/sw/src/brooms.c b/polymer/eduke32/source/sw/src/brooms.c new file mode 100644 index 000000000..ed0c23b33 --- /dev/null +++ b/polymer/eduke32/source/sw/src/brooms.c @@ -0,0 +1,737 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1996, 2005 - 3D Realms Entertainment + +This file is NOT part of Shadow Warrior version 1.2 +However, it is either an older version of a file that is, or is +some test code written during the development of Shadow Warrior. +This file is provided purely for educational interest. + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#include "build.h" +#include "editor.h" + +#include "keys.h" +#include "names2.h" +#include "game.h" + + +extern int posx, posy, posz; +extern short cursectnum; +extern short ang; +extern int horiz; +extern int qsetmode; + +BOOL FindCeilingView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum); +BOOL FindFloorView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum); +short ViewSectorInScene(short cursectnum, short type, short level); +void Message(char *string, char color); + + +void +_Assert(char *expr, char *strFile, unsigned uLine) +{ + printf(ds, "Assertion failed: %s %s, line %u\n", expr, strFile, uLine); + //DSPRINTF(ds, "Assertion failed: %s %s, line %u", expr, strFile, uLine); + MONO_PRINT(ds); + exit(0); +} + +//////////////////////////////////////////////////////////////////// +// +// FLOOR ABOVE FLOOR +// +//////////////////////////////////////////////////////////////////// + + +#define ZMAX 400 +typedef struct +{ + LONG zval[ZMAX]; + SHORT sectnum[ZMAX]; + SHORT pic[ZMAX]; + SHORT slope[ZMAX]; + SHORT zcount; +} SAVE, *SAVEp; + +SAVE save; + +BOOL FAF_DebugView = 0; +BOOL FAFon = 0; +BOOL FAF_DontMoveSectors = FALSE; + +short bak_searchsector, bak_searchwall, bak_searchstat; +extern short searchsector, searchwall, searchstat, searchit; + +VOID SetupBuildFAF(VOID); +VOID ResetBuildFAF(VOID); + +void ToggleFAF(void) +{ + if (keystatus[KEYSC_3]) + { + keystatus[KEYSC_3] = FALSE; + + FLIP(FAFon, 1); + if (FAFon) + { + SetupBuildFAF(); + } + else + { + ResetBuildFAF(); + } + } + + if (FAFon && qsetmode == 200) + { + DrawOverlapRoom(posx, posy, posz, ang, horiz, cursectnum); + + // make it so that you can edit both areas in 3D + // back up vars after the first drawrooms + bak_searchsector = searchsector; + bak_searchwall = searchwall; + bak_searchstat = searchstat; + searchit = 2; + } + + if (FAFon && qsetmode == 200 && keystatus[KEYSC_4]) + { + short match; + int tx,ty,tz; + short tsectnum; + short i; + keystatus[KEYSC_4] = FALSE; + + tx = posx; + ty = posy; + tz = posz; + tsectnum = cursectnum; + + save.zcount = 0; + + if (sector[cursectnum].ceilingpicnum == FAF_MIRROR_PIC) + { + match = ViewSectorInScene(tsectnum, VIEW_THRU_CEILING, VIEW_LEVEL1); + + FAF_DontMoveSectors = TRUE; + FindCeilingView(match, &tx, &ty, tz, &tsectnum); + FAF_DontMoveSectors = FALSE; + + posx = tx; + posy = ty; + cursectnum = tsectnum; + posz = sector[cursectnum].floorz - Z(20); + } + else if (sector[cursectnum].floorpicnum == FAF_MIRROR_PIC) + { + match = ViewSectorInScene(tsectnum, VIEW_THRU_FLOOR, VIEW_LEVEL2); + + FAF_DontMoveSectors = TRUE; + FindFloorView(match, &tx, &ty, tz, &tsectnum); + FAF_DontMoveSectors = FALSE; + + posx = tx; + posy = ty; + cursectnum = tsectnum; + posz = sector[cursectnum].ceilingz + Z(20); + } + } + + +} + + +void FAF_AfterDrawRooms(void) +{ + // make it so that you can edit both areas in 3D + // if your cursor is in the FAF_MIRROR_PIC area use the vars from the first + // drawrooms instead + if ((searchstat == 1 && sector[searchsector].ceilingpicnum == FAF_MIRROR_PIC) || + (searchstat == 2 && sector[searchsector].floorpicnum == FAF_MIRROR_PIC)) + { + searchsector = bak_searchsector; + searchwall = bak_searchwall; + searchstat = bak_searchstat; + } +} + +VOID +SetupBuildFAF(VOID) +{ + short i, nexti; + SPRITEp sp,vc_sp,vf_sp,vl_sp; + short SpriteNum, NextSprite; + short vc,nextvc,vf,nextvf,l,nextl; + int zdiff; + + // move every sprite to the correct list + TRAVERSE_SPRITE_STAT(headspritestat[STAT_DEFAULT], SpriteNum, NextSprite) + { + sp = &sprite[SpriteNum]; + + if (sp->picnum != ST1) + continue; + + switch (sp->hitag) + { + case VIEW_THRU_CEILING: + case VIEW_THRU_FLOOR: + { + int i,nexti; + // make sure there is only one set per level of these + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + if (sprite[i].hitag == sp->hitag && sprite[i].lotag == sp->lotag) + { + sprintf(ds,"Two VIEW_THRU_ tags with same match found on level\n1: x %d, y %d \n2: x %d, y %d", sp->x, sp->y, sprite[i].x, sprite[i].y); + Message(ds,0); + } + } + + changespritestat(SpriteNum, STAT_FAF); + break; + } + + case VIEW_LEVEL1: + case VIEW_LEVEL2: + case VIEW_LEVEL3: + case VIEW_LEVEL4: + case VIEW_LEVEL5: + case VIEW_LEVEL6: + { + changespritestat(SpriteNum, STAT_FAF); + break; + } + } + } + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sector[sp->sectnum].ceilingpicnum == FAF_PLACE_MIRROR_PIC) + { + sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC; + if (sector[sp->sectnum].floorz == sector[sp->sectnum].ceilingz) + { + sprintf(ds, "Mirror used for non-connect area. Use tile 342. Sect %d, x %d, y %d\n", sp->sectnum, wall[sector[sp->sectnum].wallptr].x, wall[sector[sp->sectnum].wallptr].y); + Message(ds,0); + } + } + + if (sector[sp->sectnum].floorpicnum == FAF_PLACE_MIRROR_PIC) + { + sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC; + if (sector[sp->sectnum].floorz == sector[sp->sectnum].ceilingz) + { + sprintf(ds, "Mirror used for non-connect area. Use tile 342. Sect %d, x %d, y %d\n", sp->sectnum, wall[sector[sp->sectnum].wallptr].x, wall[sector[sp->sectnum].wallptr].y); + Message(ds,0); + } + } + + if (sector[sp->sectnum].ceilingpicnum == FAF_PLACE_MIRROR_PIC+1) + sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1; + + if (sector[sp->sectnum].floorpicnum == FAF_PLACE_MIRROR_PIC+1) + sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1; + } + + + for (i = 0; i < numwalls; i++) + { + if (wall[i].picnum == FAF_PLACE_MIRROR_PIC) + wall[i].picnum = FAF_MIRROR_PIC; + + if (wall[i].picnum == FAF_PLACE_MIRROR_PIC+1) + wall[i].picnum = FAF_MIRROR_PIC+1; + } + +#if 0 + // check ceiling and floor heights + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], vc, nextvc) + { + vc_sp = &sprite[vc]; + + if (vc_sp->hitag == VIEW_THRU_CEILING) + { + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], vf, nextvf) + { + vf_sp = &sprite[vf]; + + if (vf_sp->hitag == VIEW_THRU_FLOOR && vf_sp->lotag == vc_sp->lotag) + { + zdiff = labs(sector[vc_sp->sectnum].ceilingz - sector[vf_sp->sectnum].floorz); + + //DSPRINTF(ds,"zdiff %d",zdiff); + MONO_PRINT(ds); + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], l, nextl) + { + vl_sp = &sprite[l]; + + if (vl_sp->hitag == VIEW_LEVEL1) + { + if (sector[vl_sp->sectnum].ceilingz < sector[vc_sp->sectnum].ceilingz + zdiff) + { + sprintf(ds,"Sector %d (x %d, y %d) ceiling z to close to VIEW_THRU_CEILING z", + vl_sp->sectnum, wall[sector[vl_sp->sectnum].wallptr].x, wall[sector[vl_sp->sectnum].wallptr].y); + Message(ds,0); + } + } + else if (vl_sp->hitag == VIEW_LEVEL2) + { + if (sector[vl_sp->sectnum].floorz > sector[vf_sp->sectnum].floorz + zdiff) + { + sprintf(ds,"Sector %d (x %d, y %d)floor z to close to VIEW_THRU_FLOOR z", + vl_sp->sectnum, wall[sector[vl_sp->sectnum].wallptr].x, wall[sector[vl_sp->sectnum].wallptr].y); + Message(ds,0); + } + } + } + } + } + } + } +#endif + +} + +VOID +ResetBuildFAF(VOID) +{ + short i, nexti; + SPRITEp sp; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sector[sp->sectnum].ceilingpicnum == FAF_MIRROR_PIC) + sector[sp->sectnum].ceilingpicnum = FAF_PLACE_MIRROR_PIC; + + if (sector[sp->sectnum].floorpicnum == FAF_MIRROR_PIC) + sector[sp->sectnum].floorpicnum = FAF_PLACE_MIRROR_PIC; + + if (sector[sp->sectnum].ceilingpicnum == FAF_MIRROR_PIC+1) + sector[sp->sectnum].ceilingpicnum = FAF_PLACE_MIRROR_PIC+1; + + if (sector[sp->sectnum].floorpicnum == FAF_MIRROR_PIC+1) + sector[sp->sectnum].floorpicnum = FAF_PLACE_MIRROR_PIC+1; + } + + for (i = 0; i < numwalls; i++) + { + if (wall[i].picnum == FAF_MIRROR_PIC) + wall[i].picnum = FAF_PLACE_MIRROR_PIC; + + if (wall[i].picnum == FAF_MIRROR_PIC+1) + wall[i].picnum = FAF_PLACE_MIRROR_PIC+1; + } + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + changespritestat(i, STAT_DEFAULT); + } +} + + +BOOL +PicInView(short tile_num, BOOL reset) +{ + if (TEST(gotpic[tile_num >> 3], 1 << (tile_num & 7))) + { + if (reset) + RESET(gotpic[tile_num >> 3], 1 << (tile_num & 7)); + + return TRUE; + } + + return FALSE; +} + +void +GetUpperLowerSector(short match, int x, int y, short *upper, short *lower) +{ + int i, j; + short sectorlist[16]; + short sln = 0; + short SpriteNum, Next; + SPRITEp sp; + + // didn't find it yet so test ALL sectors + if (sln < 2) + { + sln = 0; + for (i = numsectors - 1; i >= 0; i--) + { + if (inside(x, y, (short) i) == 1) + { + BOOL found = FALSE; + + TRAVERSE_SPRITE_SECT(headspritesect[i], SpriteNum, Next) + { + sp = &sprite[SpriteNum]; + + if (sp->statnum == STAT_FAF && + (sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6) + && sp->lotag == match) + { + found = TRUE; + } + } + + if (!found) + continue; + + sectorlist[sln] = i; + sln++; + } + } + } + + if (sln == 0) + { + *upper = -1; + *lower = -1; + return; + } + + // Map rooms have NOT been dragged on top of each other + if (sln == 1) + { + *lower = sectorlist[0]; + *upper = sectorlist[0]; + return; + } + else + // Map rooms HAVE been dragged on top of each other + if (sln > 2) + { + // try again moving the x,y pos around until you only get two sectors + GetUpperLowerSector(match, x - 1, y, upper, lower); + } + + if (sln == 2) + { + if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz) + { + // swap + // make sectorlist[0] the LOW sector + short hold; + + hold = sectorlist[0]; + sectorlist[0] = sectorlist[1]; + sectorlist[1] = hold; + } + + *lower = sectorlist[0]; + *upper = sectorlist[1]; + } +} + +BOOL +FindCeilingView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum) +{ + int xoff = 0; + int yoff = 0; + short i, nexti; + SPRITEp sp = NULL; + short top_sprite = -1; + int pix_diff; + int newz; + + save.zcount = 0; + + // Search Stat List For closest ceiling view sprite + // Get the match, xoff, yoff from this point + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match) + { + xoff = *x - sp->x; + yoff = *y - sp->y; + + break; + } + } + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->lotag == match) + { + // determine x,y position + if (sp->hitag == VIEW_THRU_FLOOR) + { + short upper, lower; + + *x = sp->x + xoff; + *y = sp->y + yoff; + + // get new sector + GetUpperLowerSector(match, *x, *y, &upper, &lower); + *sectnum = upper; + break; + } + } + } + + if (*sectnum < 0) + return FALSE; + + ASSERT(sp); + ASSERT(sp->hitag == VIEW_THRU_FLOOR); + + if (FAF_DontMoveSectors) + return TRUE; + + pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8; + newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128); + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->lotag == match) + { + // move lower levels ceilings up for the correct view + if (sp->hitag == VIEW_LEVEL2) + { + // save it off + save.sectnum[save.zcount] = sp->sectnum; + save.zval[save.zcount] = sector[sp->sectnum].floorz; + save.pic[save.zcount] = sector[sp->sectnum].floorpicnum; + save.slope[save.zcount] = sector[sp->sectnum].floorheinum; + + sector[sp->sectnum].floorz = newz; + sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1; + sector[sp->sectnum].floorheinum = 0; + + save.zcount++; + ASSERT(save.zcount < ZMAX); + } + } + } + + return TRUE; +} + +BOOL +FindFloorView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum) +{ + int xoff = 0; + int yoff = 0; + short i, nexti; + SPRITEp sp = NULL; + int newz; + int pix_diff; + + save.zcount = 0; + + // Search Stat List For closest ceiling view sprite + // Get the match, xoff, yoff from this point + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match) + { + xoff = *x - sp->x; + yoff = *y - sp->y; + + break; + } + } + + + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->lotag == match) + { + // determine x,y position + if (sp->hitag == VIEW_THRU_CEILING) + { + short upper, lower; + + *x = sp->x + xoff; + *y = sp->y + yoff; + + // get new sector + GetUpperLowerSector(match, *x, *y, &upper, &lower); + *sectnum = lower; + break; + } + } + } + + if (*sectnum < 0) + return FALSE; + + ASSERT(sp); + ASSERT(sp->hitag == VIEW_THRU_CEILING); + + if (FAF_DontMoveSectors) + return TRUE; + + // move ceiling multiple of 128 so that the wall tile will line up + pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8; + newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128); + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->lotag == match) + { + // move upper levels floors down for the correct view + if (sp->hitag == VIEW_LEVEL1) + { + // save it off + save.sectnum[save.zcount] = sp->sectnum; + save.zval[save.zcount] = sector[sp->sectnum].ceilingz; + save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum; + save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum; + + sector[sp->sectnum].ceilingz = newz; + + sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1; + sector[sp->sectnum].ceilingheinum = 0; + + save.zcount++; + ASSERT(save.zcount < ZMAX); + } + } + } + + return TRUE; +} + +BOOL +SectorInScene(short tile_num) +{ + if (TEST(gotsector[tile_num >> 3], 1 << (tile_num & 7))) + { + RESET(gotsector[tile_num >> 3], 1 << (tile_num & 7)); + return TRUE; + } + + return FALSE; +} + +short +ViewSectorInScene(short cursectnum, short type, short level) +{ + int i, nexti; + int j, nextj; + SPRITEp sp; + SPRITEp sp2; + int cz, fz; + short match; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti) + { + sp = &sprite[i]; + + if (sp->hitag == level) + { + if (cursectnum == sp->sectnum) + { + // ignore case if sprite is pointing up + if (sp->ang == 1536) + continue; + + // only gets to here is sprite is pointing down + // found a potential match + match = sp->lotag; + + return match; + } + } + } + + return -1; +} + +VOID +DrawOverlapRoom(int tx, int ty, int tz, short tang, int thoriz, short tsectnum) +{ + short i; + short match; + + save.zcount = 0; + + match = ViewSectorInScene(tsectnum, VIEW_THRU_CEILING, VIEW_LEVEL1); + if (match != -1) + { + FindCeilingView(match, &tx, &ty, tz, &tsectnum); + + if (tsectnum < 0) + { + sprintf(ds,"COULD NOT FIND TAGGED LEVEL2 SECTOR FROM X %d, Y %d, SECTNUM %d.",posx,posy,cursectnum); + Message(ds, 0); + return; + } + + drawrooms(tx, ty, tz, tang, thoriz, tsectnum); + drawmasks(); + + // reset Z's + for (i = 0; i < save.zcount; i++) + { + sector[save.sectnum[i]].floorz = save.zval[i]; + sector[save.sectnum[i]].floorpicnum = save.pic[i]; + sector[save.sectnum[i]].floorheinum = save.slope[i]; + } + } + else + { + match = ViewSectorInScene(tsectnum, VIEW_THRU_FLOOR, VIEW_LEVEL2); + if (match != -1) + { + FindFloorView(match, &tx, &ty, tz, &tsectnum); + + if (tsectnum < 0) + { + sprintf(ds,"COULD NOT FIND TAGGED LEVEL1 SECTOR FROM X %d, Y %d, SECTNUM %d.",posx,posy,cursectnum); + Message(ds, 0); + return; + } + + drawrooms(tx, ty, tz, tang, thoriz, tsectnum); + drawmasks(); + + // reset Z's + for (i = 0; i < save.zcount; i++) + { + sector[save.sectnum[i]].ceilingz = save.zval[i]; + sector[save.sectnum[i]].ceilingpicnum = save.pic[i]; + sector[save.sectnum[i]].ceilingheinum = save.slope[i]; + } + } + } +} diff --git a/polymer/eduke32/source/sw/src/bunny.c b/polymer/eduke32/source/sw/src/bunny.c new file mode 100644 index 000000000..c2c758aef --- /dev/null +++ b/polymer/eduke32/source/sw/src/bunny.c @@ -0,0 +1,1630 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "tags.h" +#include "ai.h" +#include "pal.h" +#include "sprite.h" +#include "actor.h" +#include "weapon.h" +#include "track.h" + +short Bunny_Count = 0; +ANIMATOR DoActorMoveJump; +ANIMATOR DoBunnyMoveJump; +ANIMATOR DoBunnyQuickJump; + +DECISION BunnyBattle[] = +{ + {748, InitActorMoveCloser}, + {750, InitActorAlertNoise}, + {760, InitActorAttackNoise}, + {1024, InitActorMoveCloser} +}; + +DECISION BunnyOffense[] = +{ + {600, InitActorMoveCloser}, + {700, InitActorAlertNoise}, + {1024, InitActorMoveCloser} +}; + +DECISION BunnyBroadcast[] = +{ + {21, InitActorAlertNoise}, + {51, InitActorAmbientNoise}, + {1024, InitActorDecide} +}; + +DECISION BunnySurprised[] = +{ + {500, InitActorRunAway}, + {701, InitActorMoveCloser}, + {1024, InitActorDecide} +}; + +DECISION BunnyEvasive[] = +{ + {500, InitActorWanderAround}, + {1020, InitActorRunAway}, + {1024, InitActorAmbientNoise} +}; + +DECISION BunnyLostTarget[] = +{ + {900, InitActorFindPlayer}, + {1024, InitActorWanderAround} +}; + +DECISION BunnyCloseRange[] = +{ + {1024, InitActorAttack }, +// {1024, InitActorReposition } +}; + +DECISION BunnyWander[] = +{ + {1024, InitActorReposition} +}; + +PERSONALITY WhiteBunnyPersonality = +{ + BunnyBattle, + BunnyOffense, + BunnyBroadcast, + BunnySurprised, + BunnyEvasive, + BunnyLostTarget, + BunnyCloseRange, + BunnyCloseRange +}; + +PERSONALITY BunnyPersonality = +{ + BunnyEvasive, + BunnyEvasive, + BunnyEvasive, + BunnyWander, + BunnyWander, + BunnyWander, + BunnyEvasive, + BunnyEvasive +}; + +ATTRIBUTE BunnyAttrib = +{ + {100, 120, 140, 180}, // Speeds + {5, 0, -2, -4}, // Tic Adjusts + 3, // MaxWeapons; + { + DIGI_BUNNYAMBIENT, 0, DIGI_BUNNYATTACK, + DIGI_BUNNYATTACK, DIGI_BUNNYDIE2, 0, + 0,0,0,0 + } +}; + +ATTRIBUTE WhiteBunnyAttrib = +{ + {200, 220, 340, 380}, // Speeds + {5, 0, -2, -4}, // Tic Adjusts + 3, // MaxWeapons; + { + DIGI_BUNNYAMBIENT, 0, DIGI_BUNNYATTACK, + DIGI_BUNNYATTACK, DIGI_BUNNYDIE2, 0, + 0,0,0,0 + } +}; + +////////////////////// +// +// BUNNY RUN +// +////////////////////// + +#define BUNNY_RUN_RATE 10 + +ANIMATOR DoBunnyMove, NullBunny, DoActorDebris, DoBunnyGrowUp; + +STATE s_BunnyRun[5][6] = +{ + { + {BUNNY_RUN_R0 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][1]}, + {BUNNY_RUN_R0 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][2]}, + {BUNNY_RUN_R0 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][3]}, + {BUNNY_RUN_R0 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][4]}, + {BUNNY_RUN_R0 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[0][5]}, + {BUNNY_RUN_R0 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][0]}, + }, + { + {BUNNY_RUN_R1 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][1]}, + {BUNNY_RUN_R1 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][2]}, + {BUNNY_RUN_R1 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][3]}, + {BUNNY_RUN_R1 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][4]}, + {BUNNY_RUN_R1 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[1][5]}, + {BUNNY_RUN_R1 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][0]}, + }, + { + {BUNNY_RUN_R2 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][1]}, + {BUNNY_RUN_R2 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][2]}, + {BUNNY_RUN_R2 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][3]}, + {BUNNY_RUN_R2 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][4]}, + {BUNNY_RUN_R2 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[2][5]}, + {BUNNY_RUN_R2 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][0]}, + }, + { + {BUNNY_RUN_R3 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][1]}, + {BUNNY_RUN_R3 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][2]}, + {BUNNY_RUN_R3 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][3]}, + {BUNNY_RUN_R3 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][4]}, + {BUNNY_RUN_R3 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[3][5]}, + {BUNNY_RUN_R3 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][0]}, + }, + { + {BUNNY_RUN_R4 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][1]}, + {BUNNY_RUN_R4 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][2]}, + {BUNNY_RUN_R4 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][3]}, + {BUNNY_RUN_R4 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][4]}, + {BUNNY_RUN_R4 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[4][5]}, + {BUNNY_RUN_R4 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][0]}, + } +}; + + +STATEp sg_BunnyRun[] = +{ + &s_BunnyRun[0][0], + &s_BunnyRun[1][0], + &s_BunnyRun[2][0], + &s_BunnyRun[3][0], + &s_BunnyRun[4][0] +}; + +////////////////////// +// +// BUNNY STAND +// +////////////////////// + +#define BUNNY_STAND_RATE 12 +ANIMATOR DoBunnyEat; + +STATE s_BunnyStand[5][3] = +{ + { + {BUNNY_STAND_R0 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[0][1]}, + {BUNNY_STAND_R0 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[0][2]}, + {BUNNY_STAND_R0 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[0][0]}, + }, + { + {BUNNY_STAND_R1 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[1][1]}, + {BUNNY_STAND_R1 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[1][2]}, + {BUNNY_STAND_R1 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[1][0]}, + }, + { + {BUNNY_STAND_R2 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[2][1]}, + {BUNNY_STAND_R2 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[2][2]}, + {BUNNY_STAND_R2 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[2][0]}, + }, + { + {BUNNY_STAND_R3 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[3][1]}, + {BUNNY_STAND_R3 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[3][2]}, + {BUNNY_STAND_R3 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[3][0]}, + }, + { + {BUNNY_STAND_R4 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[4][1]}, + {BUNNY_STAND_R4 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[4][2]}, + {BUNNY_STAND_R4 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[4][0]}, + }, +}; + + +STATEp sg_BunnyStand[] = +{ + s_BunnyStand[0], + s_BunnyStand[1], + s_BunnyStand[2], + s_BunnyStand[3], + s_BunnyStand[4] +}; + +////////////////////// +// +// BUNNY GET LAYED +// +////////////////////// + +#define BUNNY_SCREW_RATE 16 +ANIMATOR DoBunnyScrew; + +STATE s_BunnyScrew[5][2] = +{ + { + {BUNNY_STAND_R0 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[0][1]}, + {BUNNY_STAND_R0 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[0][0]}, + }, + { + {BUNNY_STAND_R1 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[1][1]}, + {BUNNY_STAND_R1 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[1][0]}, + }, + { + {BUNNY_STAND_R2 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[2][1]}, + {BUNNY_STAND_R2 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[2][0]}, + }, + { + {BUNNY_STAND_R3 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[3][1]}, + {BUNNY_STAND_R3 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[3][0]}, + }, + { + {BUNNY_STAND_R4 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[4][1]}, + {BUNNY_STAND_R4 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[4][0]}, + }, +}; + + +STATEp sg_BunnyScrew[] = +{ + s_BunnyScrew[0], + s_BunnyScrew[1], + s_BunnyScrew[2], + s_BunnyScrew[3], + s_BunnyScrew[4] +}; + +////////////////////// +// +// BUNNY SWIPE +// +////////////////////// + +#define BUNNY_SWIPE_RATE 8 +ANIMATOR InitActorDecide; +ANIMATOR InitBunnySlash; + +STATE s_BunnySwipe[5][8] = +{ + { + {BUNNY_SWIPE_R0 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][1]}, + {BUNNY_SWIPE_R0 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][2]}, + {BUNNY_SWIPE_R0 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[0][3]}, + {BUNNY_SWIPE_R0 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][4]}, + {BUNNY_SWIPE_R0 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][5]}, + {BUNNY_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[0][6]}, + {BUNNY_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[0][7]}, + {BUNNY_SWIPE_R0 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[0][7]}, + }, + { + {BUNNY_SWIPE_R1 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][1]}, + {BUNNY_SWIPE_R1 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][2]}, + {BUNNY_SWIPE_R1 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[1][3]}, + {BUNNY_SWIPE_R1 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][4]}, + {BUNNY_SWIPE_R1 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][5]}, + {BUNNY_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[1][6]}, + {BUNNY_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[1][7]}, + {BUNNY_SWIPE_R1 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[1][7]}, + }, + { + {BUNNY_SWIPE_R2 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][1]}, + {BUNNY_SWIPE_R2 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][2]}, + {BUNNY_SWIPE_R2 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[2][3]}, + {BUNNY_SWIPE_R2 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][4]}, + {BUNNY_SWIPE_R2 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][5]}, + {BUNNY_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[2][6]}, + {BUNNY_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[2][7]}, + {BUNNY_SWIPE_R2 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[2][7]}, + }, + { + {BUNNY_SWIPE_R3 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][1]}, + {BUNNY_SWIPE_R3 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][2]}, + {BUNNY_SWIPE_R3 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[3][3]}, + {BUNNY_SWIPE_R3 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][4]}, + {BUNNY_SWIPE_R3 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][5]}, + {BUNNY_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[3][6]}, + {BUNNY_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[3][7]}, + {BUNNY_SWIPE_R3 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[3][7]}, + }, + { + {BUNNY_SWIPE_R4 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][1]}, + {BUNNY_SWIPE_R4 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][2]}, + {BUNNY_SWIPE_R4 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[4][3]}, + {BUNNY_SWIPE_R4 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][4]}, + {BUNNY_SWIPE_R4 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][5]}, + {BUNNY_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[4][6]}, + {BUNNY_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[4][7]}, + {BUNNY_SWIPE_R4 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[4][7]}, + } +}; + + +STATEp sg_BunnySwipe[] = +{ + &s_BunnySwipe[0][0], + &s_BunnySwipe[1][0], + &s_BunnySwipe[2][0], + &s_BunnySwipe[3][0], + &s_BunnySwipe[4][0] +}; + + +////////////////////// +// +// BUNNY HEART - show players heart +// +////////////////////// + +#define BUNNY_HEART_RATE 14 +ANIMATOR DoBunnyStandKill; + +STATE s_BunnyHeart[5][4] = +{ + { + {BUNNY_SWIPE_R0 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[0][0]}, + }, + { + {BUNNY_SWIPE_R1 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[1][0]}, + }, + { + {BUNNY_SWIPE_R2 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[2][0]}, + }, + { + {BUNNY_SWIPE_R3 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[3][0]}, + }, + { + {BUNNY_SWIPE_R4 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[4][0]}, + } +}; + + +STATEp sg_BunnyHeart[] = +{ + &s_BunnyHeart[0][0], + &s_BunnyHeart[1][0], + &s_BunnyHeart[2][0], + &s_BunnyHeart[3][0], + &s_BunnyHeart[4][0] +}; + +////////////////////// +// +// BUNNY PAIN +// +////////////////////// + +#define BUNNY_PAIN_RATE 38 +ANIMATOR DoBunnyPain; + +STATE s_BunnyPain[5][1] = +{ + { + {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[0][0]}, + }, + { + {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[1][0]}, + }, + { + {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[2][0]}, + }, + { + {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[3][0]}, + }, + { + {BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[4][0]}, + } +}; + +STATEp sg_BunnyPain[] = +{ + &s_BunnyPain[0][0], + &s_BunnyPain[1][0], + &s_BunnyPain[2][0], + &s_BunnyPain[3][0], + &s_BunnyPain[4][0] +}; + +////////////////////// +// +// BUNNY JUMP +// +////////////////////// + +#define BUNNY_JUMP_RATE 25 + +STATE s_BunnyJump[5][6] = +{ + { + {BUNNY_RUN_R0 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[0][1]}, + {BUNNY_RUN_R0 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[0][1]}, + }, + { + {BUNNY_RUN_R1 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[1][1]}, + {BUNNY_RUN_R1 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[1][1]}, + }, + { + {BUNNY_RUN_R2 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[2][1]}, + {BUNNY_RUN_R2 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[2][1]}, + }, + { + {BUNNY_RUN_R3 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[3][1]}, + {BUNNY_RUN_R3 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[3][1]}, + }, + { + {BUNNY_RUN_R4 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[4][1]}, + {BUNNY_RUN_R4 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[4][1]}, + } +}; + + +STATEp sg_BunnyJump[] = +{ + &s_BunnyJump[0][0], + &s_BunnyJump[1][0], + &s_BunnyJump[2][0], + &s_BunnyJump[3][0], + &s_BunnyJump[4][0] +}; + + +////////////////////// +// +// BUNNY FALL +// +////////////////////// + +#define BUNNY_FALL_RATE 25 + +STATE s_BunnyFall[5][6] = +{ + { + {BUNNY_RUN_R0 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[0][0]}, + }, + { + {BUNNY_RUN_R1 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[1][0]}, + }, + { + {BUNNY_RUN_R2 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[2][0]}, + }, + { + {BUNNY_RUN_R3 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[3][0]}, + }, + { + {BUNNY_RUN_R4 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[4][0]}, + } +}; + + +STATEp sg_BunnyFall[] = +{ + &s_BunnyFall[0][0], + &s_BunnyFall[1][0], + &s_BunnyFall[2][0], + &s_BunnyFall[3][0], + &s_BunnyFall[4][0] +}; + + +////////////////////// +// +// BUNNY JUMP ATTACK +// +////////////////////// + +#define BUNNY_JUMP_ATTACK_RATE 35 +int DoBunnyBeginJumpAttack(short SpriteNum); + +STATE s_BunnyJumpAttack[5][6] = +{ + { + {BUNNY_RUN_R0 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[0][1]}, + {BUNNY_RUN_R0 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[0][2]}, + {BUNNY_RUN_R0 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[0][2]}, + }, + { + {BUNNY_RUN_R1 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[1][1]}, + {BUNNY_RUN_R1 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[1][2]}, + {BUNNY_RUN_R1 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[1][2]}, + }, + { + {BUNNY_RUN_R2 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[2][1]}, + {BUNNY_RUN_R2 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[2][2]}, + {BUNNY_RUN_R2 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[2][2]}, + }, + { + {BUNNY_RUN_R3 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[3][1]}, + {BUNNY_RUN_R3 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[3][2]}, + {BUNNY_RUN_R3 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[3][2]}, + }, + { + {BUNNY_RUN_R4 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[4][1]}, + {BUNNY_RUN_R4 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[4][2]}, + {BUNNY_RUN_R4 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[4][2]}, + } +}; + + +STATEp sg_BunnyJumpAttack[] = +{ + &s_BunnyJumpAttack[0][0], + &s_BunnyJumpAttack[1][0], + &s_BunnyJumpAttack[2][0], + &s_BunnyJumpAttack[3][0], + &s_BunnyJumpAttack[4][0] +}; + + +////////////////////// +// +// BUNNY DIE +// +////////////////////// + +#define BUNNY_DIE_RATE 16 +ANIMATOR BunnySpew; + +STATE s_BunnyDie[] = +{ + {BUNNY_DIE + 0, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[1]}, + {BUNNY_DIE + 0, SF_QUICK_CALL, BunnySpew, &s_BunnyDie[2]}, + {BUNNY_DIE + 1, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[3]}, + {BUNNY_DIE + 2, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[4]}, + {BUNNY_DIE + 2, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[5]}, + {BUNNY_DEAD, BUNNY_DIE_RATE, DoActorDebris, &s_BunnyDie[5]}, +}; + +#define BUNNY_DEAD_RATE 8 + +STATE s_BunnyDead[] = +{ + {BUNNY_DIE + 0, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDie[1]}, + {BUNNY_DIE + 0, SF_QUICK_CALL, BunnySpew, &s_BunnyDie[2]}, + {BUNNY_DIE + 1, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDead[3]}, + {BUNNY_DIE + 2, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDead[4]}, + {BUNNY_DEAD, SF_QUICK_CALL, QueueFloorBlood, &s_BunnyDead[5]}, + {BUNNY_DEAD, BUNNY_DEAD_RATE, DoActorDebris, &s_BunnyDead[5]}, +}; + +STATEp sg_BunnyDie[] = +{ + s_BunnyDie +}; + +STATEp sg_BunnyDead[] = +{ + s_BunnyDead +}; + +STATE s_BunnyDeathJump[] = +{ + {BUNNY_DIE + 0, BUNNY_DIE_RATE, DoActorDeathMove, &s_BunnyDeathJump[0]} +}; + +STATE s_BunnyDeathFall[] = +{ + {BUNNY_DIE + 1, BUNNY_DIE_RATE, DoActorDeathMove, &s_BunnyDeathFall[0]} +}; + +STATEp sg_BunnyDeathJump[] = +{ + s_BunnyDeathJump +}; + +STATEp sg_BunnyDeathFall[] = +{ + s_BunnyDeathFall +}; + + +/* +STATEp *Stand[MAX_WEAPONS]; +STATEp *Run; +STATEp *Jump; +STATEp *Fall; +STATEp *Crawl; +STATEp *Swim; +STATEp *Fly; +STATEp *Rise; +STATEp *Sit; +STATEp *Look; +STATEp *Climb; +STATEp *Pain; +STATEp *Death1; +STATEp *Death2; +STATEp *Dead; +STATEp *DeathJump; +STATEp *DeathFall; +STATEp *CloseAttack[2]; +STATEp *Attack[6]; +STATEp *Special[2]; +*/ + +ACTOR_ACTION_SET BunnyActionSet = +{ + sg_BunnyStand, + sg_BunnyRun, + sg_BunnyJump, + sg_BunnyFall, + NULL, // sg_BunnyCrawl, + NULL, // sg_BunnySwim, + NULL, // sg_BunnyFly, + NULL, // sg_BunnyRise, + NULL, // sg_BunnySit, + NULL, // sg_BunnyLook, + NULL, // climb + sg_BunnyPain, + sg_BunnyDie, + NULL, + sg_BunnyDead, + sg_BunnyDeathJump, + sg_BunnyDeathFall, + {NULL}, + {1024}, + {NULL}, + {1024}, + {sg_BunnyHeart, sg_BunnyRun}, + NULL, + NULL +}; + +ACTOR_ACTION_SET BunnyWhiteActionSet = +{ + sg_BunnyStand, + sg_BunnyRun, + sg_BunnyJump, + sg_BunnyFall, + NULL, // sg_BunnyCrawl, + NULL, // sg_BunnySwim, + NULL, // sg_BunnyFly, + NULL, // sg_BunnyRise, + NULL, // sg_BunnySit, + NULL, // sg_BunnyLook, + NULL, // climb + sg_BunnyPain, // pain + sg_BunnyDie, + NULL, + sg_BunnyDead, + sg_BunnyDeathJump, + sg_BunnyDeathFall, + {sg_BunnySwipe}, + {1024}, +// {sg_BunnyJumpAttack, sg_BunnySwipe}, +// {800, 1024}, + {sg_BunnySwipe}, + {1024}, + {sg_BunnyHeart, sg_BunnySwipe}, + NULL, + NULL +}; + +int +SetupBunny(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u; + ANIMATOR DoActorDecide; + + if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + { + u = User[SpriteNum]; + ASSERT(u); + } + else + { + User[SpriteNum] = u = SpawnUser(SpriteNum, BUNNY_RUN_R0, s_BunnyRun[0]); + u->Health = 10; + } + + Bunny_Count++; + //if(Bunny_Count > 20) + // { + // KillSprite(SpriteNum); + // Bunny_Count--; + // return(0); + // } + + ChangeState(SpriteNum, s_BunnyRun[0]); + u->StateEnd = s_BunnyDie; + u->Rot = sg_BunnyRun; + //sp->xrepeat = 64; + //sp->yrepeat = 64; + u->ShellNum = 0; // Not Pregnant right now + u->FlagOwner = 0; + + sp->clipdist = (150) >> 2; + + if (sp->pal == PALETTE_PLAYER1) + { + EnemyDefaults(SpriteNum, &BunnyWhiteActionSet, &WhiteBunnyPersonality); + u->Attrib = &WhiteBunnyAttrib; + sp->xrepeat = 96; + sp->yrepeat = 90; + + sp->clipdist = 200>>2; + + if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + u->Health = 60; + } + else if (sp->pal == PALETTE_PLAYER8) // Male Rabbit + { + EnemyDefaults(SpriteNum, &BunnyActionSet, &BunnyPersonality); + u->Attrib = &BunnyAttrib; + //sp->xrepeat = 76; + //sp->yrepeat = 70; + + //sp->shade = 0; // darker + if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + u->Health = 20; + u->Flag1 = 0; + } + else + { + // Female Rabbit + EnemyDefaults(SpriteNum, &BunnyActionSet, &BunnyPersonality); + u->Attrib = &BunnyAttrib; + u->spal = sp->pal = PALETTE_PLAYER0; + u->Flag1 = SEC(5); + //sp->shade = 0; // darker + } + + DoActorSetSpeed(SpriteNum, FAST_SPEED); + + SET(u->Flags, SPR_XFLIP_TOGGLE); + + + u->zclip = Z(16); + u->floor_dist = Z(8); + u->ceiling_dist = Z(8); + u->lo_step = Z(16); + + return 0; +} + +int +GetBunnyJumpHeight(short jump_speed, short jump_grav) +{ + int jump_iterations; + int height; + + jump_speed = labs(jump_speed); + + jump_iterations = jump_speed / (jump_grav * ACTORMOVETICS); + + height = jump_speed * jump_iterations * ACTORMOVETICS; + + height = DIV256(height); + + return DIV2(height); +} + +int +PickBunnyJumpSpeed(short SpriteNum, int pix_height) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + ASSERT(pix_height < 128); + + u->jump_speed = -600; + u->jump_grav = 8; + + while (TRUE) + { + if (GetBunnyJumpHeight(u->jump_speed, u->jump_grav) > pix_height + 20) + break; + + u->jump_speed -= 100; + + ASSERT(u->jump_speed > -3000); + } + + return u->jump_speed; +} + +// +// JUMP ATTACK +// + +int +DoBunnyBeginJumpAttack(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + SPRITEp psp = User[SpriteNum]->tgt_sp; + int dist; + int CanSeePlayer(short SpriteNum); + short tang; + + +#define RANDOM_NEG(x) (RANDOM_P2((x)<<1) - (x)) + + tang = getangle(psp->x - sp->x, psp->y - sp->y); + + if (move_sprite(SpriteNum, sintable[NORM_ANGLE(tang+512)] >> 7, sintable[tang] >> 7, + 0L, u->ceiling_dist, u->floor_dist, CLIPMASK_ACTOR, ACTORMOVETICS)) + sp->ang = NORM_ANGLE(sp->ang + 1024) + (RANDOM_NEG(256 << 6) >> 6); + else + sp->ang = NORM_ANGLE(tang + (RANDOM_NEG(256 << 6) >> 6)); + + DoActorSetSpeed(SpriteNum, FAST_SPEED); + + //u->jump_speed = -800; + PickJumpMaxSpeed(SpriteNum, -400); // was -800 + + SET(u->Flags, SPR_JUMPING); + RESET(u->Flags, SPR_FALLING); + + // set up individual actor jump gravity + u->jump_grav = 17; // was 8 + + // if I didn't do this here they get stuck in the air sometimes + DoActorZrange(SpriteNum); + + DoJump(SpriteNum); + + return 0; +} + +int +DoBunnyMoveJump(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + int nx, ny; + + // Move while jumping + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + move_actor(SpriteNum, nx, ny, 0L); + + if (TEST(u->Flags, SPR_JUMPING)) + DoActorJump(SpriteNum); + else + DoActorFall(SpriteNum); + } + + DoActorZrange(SpriteNum); + + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { +// if (DoBunnyQuickJump(SpriteNum)) +// return (0); + + InitActorDecide(SpriteNum); + } + + return 0; +} + +int +DoPickCloseBunny(short SpriteNum) +{ + USERp u = User[SpriteNum],tu; + SPRITEp sp = &sprite[SpriteNum],tsp; + int dist, near_dist = 1000, a,b,c; + short i, nexti; + //short BunnyCount=0, Bunny_Result = -1; + + // if actor can still see the player + int look_height = SPRITEp_TOS(sp); + BOOL ICanSee = FALSE; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti) + { + tsp = &sprite[i]; + tu = User[i]; + + if (sp == tsp) continue; + + if (tu->ID != BUNNY_RUN_R0) continue; + + DISTANCE(tsp->x, tsp->y, sp->x, sp->y, dist, a, b, c); + + if (dist > near_dist) continue; + + ICanSee = FAFcansee(sp->x, sp->y, look_height, sp->sectnum, tsp->x, tsp->y, SPRITEp_UPPER(tsp), tsp->sectnum); + + if (ICanSee && dist < near_dist && tu->ID == BUNNY_RUN_R0) + { + near_dist = dist; + u->tgt_sp = u->lo_sp = tsp; + //Bunny_Result = i; + return i; + } + } + return -1; +} + +int +DoBunnyQuickJump(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + if (u->spal != PALETTE_PLAYER8) return FALSE; + + if (!u->lo_sp && u->spal == PALETTE_PLAYER8 && MoveSkip4) + DoPickCloseBunny(SpriteNum); + + // Random Chance of like sexes fighting + if (u->lo_sp) + { + short hitsprite = u->lo_sp - sprite; + SPRITEp tsp = u->lo_sp; + USERp tu = User[hitsprite]; + + if (!tu || tu->ID != BUNNY_RUN_R0) return FALSE; + + + // Not mature enough yet + if (sp->xrepeat != 64 || sp->yrepeat != 64) return FALSE; + if (tsp->xrepeat != 64 || tsp->yrepeat != 64) return FALSE; + + // Kill a rival + // Only males fight + if (tu->spal == sp->pal && RANDOM_RANGE(1000) > 995) + { + if (u->spal == PALETTE_PLAYER8 && tu->spal == PALETTE_PLAYER8) + { + PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_BUNNYDIE2, &tsp->x, &tsp->y, &tsp->z, v3df_follow); + tu->Health = 0; + + // Blood fountains + InitBloodSpray(hitsprite,TRUE,-1); + + if (SpawnShrap(hitsprite, SpriteNum)) + { + SetSuicide(hitsprite); + } + else + DoActorDie(hitsprite, SpriteNum); + + Bunny_Count--; // Bunny died + + u->lo_sp = NULL; + return TRUE; + } + } + } + + // Get layed! + if (u->lo_sp && u->spal == PALETTE_PLAYER8) // Only males check this + { + short hitsprite = u->lo_sp - sprite; + SPRITEp tsp = u->lo_sp; + USERp tu = User[hitsprite]; + + + if (!tu || tu->ID != BUNNY_RUN_R0) return FALSE; + + // Not mature enough to mate yet + if (sp->xrepeat != 64 || sp->yrepeat != 64) return FALSE; + if (tsp->xrepeat != 64 || tsp->yrepeat != 64) return FALSE; + + if (tu->ShellNum <= 0 && tu->WaitTics <= 0 && u->WaitTics <= 0) + { + if (TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY)) + { + PLAYERp pp = NULL; + + if (RANDOM_RANGE(1000) < 995 && tu->spal != PALETTE_PLAYER0) return FALSE; + + DoActorPickClosePlayer(SpriteNum); + + if (User[u->tgt_sp-sprite]->PlayerP) + pp = User[u->tgt_sp-sprite]->PlayerP; + + if (tu->spal != PALETTE_PLAYER0) + { + if (tu->Flag1 > 0) return FALSE; + tu->FlagOwner = 1; // FAG! + tu->Flag1 = SEC(10); + if (pp) + { + short choose_snd; + int fagsnds[] = {DIGI_FAGRABBIT1,DIGI_FAGRABBIT2,DIGI_FAGRABBIT3}; + + if (pp == Player+myconnectindex) + { + choose_snd = STD_RANDOM_RANGE(2<<8)>>8; + if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp)) + PlayerSound(fagsnds[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_doppler|v3df_follow|v3df_dontpan,pp); + } + } + } + else + { + if (pp && RANDOM_RANGE(1000) > 200) + { + short choose_snd; + int straightsnds[] = {DIGI_RABBITHUMP1,DIGI_RABBITHUMP2, + DIGI_RABBITHUMP3,DIGI_RABBITHUMP4}; + + if (pp == Player+myconnectindex) + { + choose_snd = STD_RANDOM_RANGE(3<<8)>>8; + if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp)) + PlayerSound(straightsnds[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_doppler|v3df_follow|v3df_dontpan,pp); + } + } + } + + sp->x = tsp->x; // Mount up little bunny + sp->y = tsp->y; + sp->ang = tsp->ang; + sp->ang = NORM_ANGLE(sp->ang + 1024); + HelpMissileLateral(SpriteNum, 2000L); + sp->ang = tsp->ang; + u->Vis = sp->ang; // Remember angles for later + tu->Vis = tsp->ang; + + NewStateGroup(SpriteNum, sg_BunnyScrew); + NewStateGroup(hitsprite, sg_BunnyScrew); + if (gs.ParentalLock || Global_PLock) + { + SET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' invisible + SET(tsp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' invisible + } + u->WaitTics = tu->WaitTics = SEC(10); // Mate for this long + return TRUE; + } + } + } + + return FALSE; +} + + +int +NullBunny(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + if (TEST(u->Flags, SPR_JUMPING)) + DoActorJump(SpriteNum); + else + DoActorFall(SpriteNum); + } + + // stay on floor unless doing certain things + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + KeepActorOnFloor(SpriteNum); + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + return 0; +} + + +int DoBunnyPain(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + NullBunny(SpriteNum); + + if ((u->WaitTics -= ACTORMOVETICS) <= 0) + InitActorDecide(SpriteNum); + return 0; +} + +int DoBunnyRipHeart(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + SPRITEp tsp = u->tgt_sp; + + NewStateGroup(SpriteNum, sg_BunnyHeart); + u->WaitTics = 6 * 120; + + // player face bunny + tsp->ang = getangle(sp->x - tsp->x, sp->y - tsp->y); + return 0; +} + +int DoBunnyStandKill(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + NullBunny(SpriteNum); + + // Growl like the bad ass bunny you are! + if (RANDOM_RANGE(1000) > 800) + PlaySound(DIGI_BUNNYATTACK,&sp->x,&sp->y,&sp->z,v3df_none); + + if ((u->WaitTics -= ACTORMOVETICS) <= 0) + NewStateGroup(SpriteNum, sg_BunnyRun); + return 0; +} + +void BunnyHatch(short Weapon) +{ + SPRITEp wp = &sprite[Weapon]; + USERp wu = User[Weapon]; + + short new,i; + SPRITEp np; + USERp nu; +#define MAX_BUNNYS 1 + short rip_ang[MAX_BUNNYS]; + + rip_ang[0] = RANDOM_P2(2048); + + for (i = 0; i < MAX_BUNNYS; i++) + { + new = COVERinsertsprite(wp->sectnum, STAT_DEFAULT); + np = &sprite[new]; + memset(np,0,sizeof(SPRITE)); + np->sectnum = wp->sectnum; + np->statnum = STAT_DEFAULT; + np->x = wp->x; + np->y = wp->y; + np->z = wp->z; + np->owner = -1; + np->xrepeat = 30; // Baby size + np->yrepeat = 24; + np->ang = rip_ang[i]; + np->pal = 0; + SetupBunny(new); + nu = User[new]; + np->shade = wp->shade; + + // make immediately active + SET(nu->Flags, SPR_ACTIVE); + if (RANDOM_RANGE(1000) > 500) // Boy or Girl? + nu->spal = np->pal = PALETTE_PLAYER0; // Girl + else + { + nu->spal = np->pal = PALETTE_PLAYER8; // Boy + // Oops, mommy died giving birth to a boy + if (RANDOM_RANGE(1000) > 500) + { + wu->Health = 0; + Bunny_Count--; // Bunny died + + // Blood fountains + InitBloodSpray(Weapon,TRUE,-1); + + if (SpawnShrap(Weapon, new)) + { + SetSuicide(Weapon); + } + else + DoActorDie(Weapon, new); + } + } + + nu->ShellNum = 0; // Not Pregnant right now + + NewStateGroup(new, nu->ActorActionSet->Jump); + nu->ActorActionFunc = DoActorMoveJump; + DoActorSetSpeed(new, FAST_SPEED); + PickJumpMaxSpeed(new, -600); + + SET(nu->Flags, SPR_JUMPING); + RESET(nu->Flags, SPR_FALLING); + + nu->jump_grav = 8; + + // if I didn't do this here they get stuck in the air sometimes + DoActorZrange(new); + + DoActorJump(new); + } +} + +int BunnyHatch2(short Weapon) +{ + SPRITEp wp = &sprite[Weapon]; + USERp wu = User[Weapon]; + + short new,i; + SPRITEp np; + USERp nu; + + new = COVERinsertsprite(wp->sectnum, STAT_DEFAULT); + np = &sprite[new]; + memset(np,0,sizeof(SPRITE)); + np->sectnum = wp->sectnum; + np->statnum = STAT_DEFAULT; + np->x = wp->x; + np->y = wp->y; + np->z = wp->z; + np->owner = -1; + np->xrepeat = 30; // Baby size + np->yrepeat = 24; + np->ang = RANDOM_P2(2048); + np->pal = 0; + SetupBunny(new); + nu = User[new]; + np->shade = wp->shade; + + // make immediately active + SET(nu->Flags, SPR_ACTIVE); + if (RANDOM_RANGE(1000) > 500) // Boy or Girl? + { + nu->spal = np->pal = PALETTE_PLAYER0; // Girl + nu->Flag1 = SEC(5); + } + else + { + nu->spal = np->pal = PALETTE_PLAYER8; // Boy + nu->Flag1 = 0; + } + + nu->ShellNum = 0; // Not Pregnant right now + + NewStateGroup(new, nu->ActorActionSet->Jump); + nu->ActorActionFunc = DoActorMoveJump; + DoActorSetSpeed(new, FAST_SPEED); + if (TEST_BOOL3(wp)) + { + PickJumpMaxSpeed(new, -600-RANDOM_RANGE(600)); + np->xrepeat = np->yrepeat = 64; + np->xvel = 150 + RANDOM_RANGE(1000); + nu->Health = 1; // Easy to pop. Like shootn' skeet. + np->ang -= RANDOM_RANGE(128); + np->ang += RANDOM_RANGE(128); + } + else + PickJumpMaxSpeed(new, -600); + + SET(nu->Flags, SPR_JUMPING); + RESET(nu->Flags, SPR_FALLING); + + nu->jump_grav = 8; + nu->FlagOwner = 0; + + nu->active_range = 75000; // Set it far + + // if I didn't do this here they get stuck in the air sometimes + DoActorZrange(new); + + DoActorJump(new); + + return new; +} + +int +DoBunnyMove(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + // Parental lock crap + if (TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) + RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' back on + + // Sometimes they just won't die! + if (u->Health <= 0) + SetSuicide(SpriteNum); + + if (u->scale_speed) + { + DoScaleSprite(SpriteNum); + } + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + if (TEST(u->Flags, SPR_JUMPING)) + DoActorJump(SpriteNum); + else + DoActorFall(SpriteNum); + } + + // if on a player/enemy sprite jump quickly + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + DoBunnyQuickJump(SpriteNum); + } + + if (TEST(u->Flags, SPR_SLIDING)) + DoActorSlide(SpriteNum); + + if (u->track >= 0) + ActorFollowTrack(SpriteNum, ACTORMOVETICS); + else + (*u->ActorActionFunc)(SpriteNum); + + // stay on floor unless doing certain things + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + KeepActorOnFloor(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + if (RANDOM_RANGE(1000) > 985 && sp->pal != PALETTE_PLAYER1 && u->track < 0) + { + switch (sector[sp->sectnum].floorpicnum) + { + case 153: + case 154: + case 193: + case 219: + case 2636: + case 2689: + case 3561: + case 3562: + case 3563: + case 3564: + NewStateGroup(SpriteNum,sg_BunnyStand); + break; + default: + sp->ang = NORM_ANGLE(RANDOM_RANGE(2048 << 6) >> 6); + u->jump_speed = -350; + DoActorBeginJump(SpriteNum); + u->ActorActionFunc = DoActorMoveJump; + break; + } + } + + return 0; +} + +int +BunnySpew(short SpriteNum) +{ + //InitBloodSpray(SpriteNum,TRUE,-1); + InitBloodSpray(SpriteNum,TRUE,-1); + return 0; +} + +int +DoBunnyEat(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + if (TEST(u->Flags, SPR_JUMPING)) + DoActorJump(SpriteNum); + else + DoActorFall(SpriteNum); + } + + // if on a player/enemy sprite jump quickly + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + DoBunnyQuickJump(SpriteNum); + } + + if (TEST(u->Flags, SPR_SLIDING)) + DoActorSlide(SpriteNum); + + // stay on floor unless doing certain things + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + KeepActorOnFloor(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + switch (sector[sp->sectnum].floorpicnum) + { + case 153: + case 154: + case 193: + case 219: + case 2636: + case 2689: + case 3561: + case 3562: + case 3563: + case 3564: + if (RANDOM_RANGE(1000) > 970) + NewStateGroup(SpriteNum,sg_BunnyRun); + break; + default: + NewStateGroup(SpriteNum,sg_BunnyRun); + break; + } + return 0; +} + +int +DoBunnyScrew(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + int dist; + + if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + { + if (TEST(u->Flags, SPR_JUMPING)) + DoActorJump(SpriteNum); + else + DoActorFall(SpriteNum); + } + + if (TEST(u->Flags, SPR_SLIDING)) + DoActorSlide(SpriteNum); + + // stay on floor unless doing certain things + if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING)) + KeepActorOnFloor(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + if (RANDOM_RANGE(1000) > 990) // Bunny sex sounds + { + if (!gs.ParentalLock && !Global_PLock) + PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_follow); + } + + u->WaitTics -= ACTORMOVETICS; + + if ((u->FlagOwner || u->spal == PALETTE_PLAYER0) && u->WaitTics > 0) // Keep Girl still + NewStateGroup(SpriteNum,sg_BunnyScrew); + + if (u->spal == PALETTE_PLAYER0 && u->WaitTics <= 0) // Female has baby + { + u->Flag1 = SEC(5); // Count down to babies + u->ShellNum = 1; // She's pregnant now + } + + if (u->WaitTics <= 0) + { + RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' back on + u->FlagOwner = 0; + NewStateGroup(SpriteNum,sg_BunnyRun); + } + + return 0; +} + +int +DoBunnyGrowUp(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + if (sp->pal == PALETTE_PLAYER1) return 0; // Don't bother white bunnies + + if ((u->Counter -= ACTORMOVETICS) <= 0) + { + if ((++sp->xrepeat) > 64) sp->xrepeat = 64; + if ((++sp->yrepeat) > 64) sp->yrepeat = 64; + u->Counter = 60; + } + + // Don't go homo too much! + if (sp->pal != PALETTE_PLAYER0 && u->Flag1 > 0) + u->Flag1 -= ACTORMOVETICS; + + // Gestation period for female rabbits + if (sp->pal == PALETTE_PLAYER0 && u->ShellNum > 0) + { + if ((u->Flag1 -= ACTORMOVETICS) <= 0) + { + if (Bunny_Count < 20) + { + PlaySound(DIGI_BUNNYDIE2, &sp->x, &sp->y, &sp->z, v3df_follow); + BunnyHatch(SpriteNum); // Baby time + } + u->ShellNum = 0; // Not pregnent anymore + } + } + + return 0; +} + + +#include "saveable.h" + +static saveable_code saveable_bunny_code[] = +{ + SAVE_CODE(SetupBunny), + SAVE_CODE(GetBunnyJumpHeight), + SAVE_CODE(PickBunnyJumpSpeed), + SAVE_CODE(DoBunnyBeginJumpAttack), + SAVE_CODE(DoBunnyMoveJump), + SAVE_CODE(DoPickCloseBunny), + SAVE_CODE(DoBunnyQuickJump), + SAVE_CODE(NullBunny), + SAVE_CODE(DoBunnyPain), + SAVE_CODE(DoBunnyRipHeart), + SAVE_CODE(DoBunnyStandKill), + SAVE_CODE(BunnyHatch), + SAVE_CODE(BunnyHatch2), + SAVE_CODE(DoBunnyMove), + SAVE_CODE(BunnySpew), + SAVE_CODE(DoBunnyEat), + SAVE_CODE(DoBunnyScrew), + SAVE_CODE(DoBunnyGrowUp), +}; + +static saveable_data saveable_bunny_data[] = +{ + SAVE_DATA(BunnyBattle), + SAVE_DATA(BunnyOffense), + SAVE_DATA(BunnyBroadcast), + SAVE_DATA(BunnySurprised), + SAVE_DATA(BunnyEvasive), + SAVE_DATA(BunnyLostTarget), + SAVE_DATA(BunnyCloseRange), + SAVE_DATA(BunnyWander), + + SAVE_DATA(WhiteBunnyPersonality), + SAVE_DATA(BunnyPersonality), + + SAVE_DATA(WhiteBunnyAttrib), + SAVE_DATA(BunnyAttrib), + + SAVE_DATA(s_BunnyRun), + SAVE_DATA(sg_BunnyRun), + SAVE_DATA(s_BunnyStand), + SAVE_DATA(sg_BunnyStand), + SAVE_DATA(s_BunnyScrew), + SAVE_DATA(sg_BunnyScrew), + SAVE_DATA(s_BunnySwipe), + SAVE_DATA(sg_BunnySwipe), + SAVE_DATA(s_BunnyHeart), + SAVE_DATA(sg_BunnyHeart), + SAVE_DATA(s_BunnyPain), + SAVE_DATA(sg_BunnyPain), + SAVE_DATA(s_BunnyJump), + SAVE_DATA(sg_BunnyJump), + SAVE_DATA(s_BunnyFall), + SAVE_DATA(sg_BunnyFall), + SAVE_DATA(s_BunnyJumpAttack), + SAVE_DATA(sg_BunnyJumpAttack), + SAVE_DATA(s_BunnyDie), + SAVE_DATA(sg_BunnyDie), + SAVE_DATA(s_BunnyDead), + SAVE_DATA(sg_BunnyDead), + SAVE_DATA(s_BunnyDeathJump), + SAVE_DATA(sg_BunnyDeathJump), + SAVE_DATA(s_BunnyDeathFall), + SAVE_DATA(sg_BunnyDeathFall), + + SAVE_DATA(BunnyActionSet), + SAVE_DATA(BunnyWhiteActionSet), +}; + +saveable_module saveable_bunny = +{ + // code + saveable_bunny_code, + SIZ(saveable_bunny_code), + + // data + saveable_bunny_data, + SIZ(saveable_bunny_data) +}; diff --git a/polymer/eduke32/source/sw/src/cache.c b/polymer/eduke32/source/sw/src/cache.c new file mode 100644 index 000000000..cbc6a7b12 --- /dev/null +++ b/polymer/eduke32/source/sw/src/cache.c @@ -0,0 +1,728 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +/**************************************** +Removed sounds that were causing "Could +not load" error messages. +****************************************/ + +#include "build.h" + +#include "names2.h" +#include "game.h" +#include "tags.h" +#include "common_game.h" +#include "break.h" +#include "quake.h" +#include "pal.h" +#include "cache.h" +#include "sounds.h" +#include "net.h" + +// Run the game with the -CACHEPRINT option and redirect to a file. +// It will save out the tile and sound number every time one caches. +// +// sw -map $bullet -cacheprint > foofile +extern BOOL PreCaching; + +// player weaponry, item usage, etc. Precache every time. +short Player_SCTable[] = +{ + 1,2,3,4,5,6,7,8,9,10, // weapons + 11,12,14,16,18,20, + 22,23,24,25,26,27,28,30, + 31,32,33,34,35,40,145,291,445,362,269, + 158,476, // underwater + 47,359, // cloaking + 48,50, // dead head + 196,52,53,54,55, // splash & getting items + 56,57,58,73,74,410, // bodies hitting ground + 484,442, // teleport & respawn + 417,418, // healing + 238,239,240,241,242,243,244, // bring weapons up + 181,182,183,184,187,216, // explosions + 272,273,274,275,486, // nuke associated sounds + 276,277,278,279,477, // chem bomb + 280,281,282,283,284,288,289,290,450, // various player sounds + 295, // armor hit + 312, // sword clank + 324,325,209, // unlocking sound + 395,396,411, // gibs + 175, // drip + 435,436,311,221,220,227, // breakage + 246,247,248,249,250,251,252,253,254,255,256, // common player talk + 257,258,259,260,261,262,263,264,266,267,438,439,440,441, + 326, // ancient chinese secret + 330,331,332,333,334,335,336,337,338,339,340, // player kill talk + 341,342,343,344,345,346,347,348, + 376,377,378,379,380,381,382,383,384,385,386,387, // more asst. talking + 370,443 // repair talk +}; + +// Actor specific sound tables. Cache only if the actor appears on the map. +// Exceptions would include ghosts, which are spawned by coolies, and +// rippers, which are spawned by the serpent boss. +short Coolie_SCTable[] = +{ + 75,76,77,78,79 +}; + +short Ghost_SCTable[] = +{ + 80,81,82,83,84,85,86,87,213 +}; + +short Ninja_SCTable[] = +{ + 88,89,90,91,92,93,94,412, + 319, // firing sound + 430 // death by sword +}; + +short Ripper_SCTable[] = +{ + 95,96,97,98,99,100,431 +}; + +short Ripper2_SCTable[] = +{ + 313,314,315,316,317,318,431 +}; + +short Head_SCTable[] = +{ + 115,116,117,118 // accursed heads +}; + +short Hornet_SCTable[] = +{ + 119,120,121,122 +}; + +short Guardian_SCTable[] = +{ + 101,102,103,104,105,106,107 +}; + +short Serpent_SCTable[] = +{ + 123,124,125,126,127,128,129,130,131 // serpent boss +}; + +short Sumo_SCTable[] = +{ + 320,321,322,323 // sumo boss +}; + +short Bunny_SCTable[] = +{ + 424,425,426,427,428 +}; + +short Toilet_SCTable[] = +{ + 388,389,390,391,392,393,488,489,490 // anime girl on toilet +}; // I suspect some of these are no longer in use + +short Trash_SCTable[] = +{ + 416 // I heard the trash can was an actor, so here is is +}; + +short Pachinko_SCTable[] = +{ + 419,420,421,422,423 +}; + +void PreCacheSoundList(short table[], int num); +void PreCacheTable(short table[], int num); +VOID PreCacheGhost(VOID); + +void +SetupPreCache(void) +{ + if (PreCaching) + { + precache(); + + PreCacheSoundList(Player_SCTable, SIZ(Player_SCTable)); + + // actors cache ranges are called from SpriteSetup + // only caches the actor if its on the level + + // weapons + PreCacheRange(2000, 2227); + PreCacheRange(4090, 4093); + // Explosions + PreCacheRange(3072, 3225); + // ninja player character + PreCacheRange(1024, 1175); + // console + PreCacheRange(2380, 2409); + PreCacheRange(3600, 3645); + PreCacheRange(2434, 2435); + // common + PreCacheRange(204, 208); + // message font + PreCacheRange(4608, 4701); + // gibs + PreCacheRange(1150,1568); + PreCacheRange(1685,1690); + PreCacheRange(900,944); + PreCacheRange(1670,1681); + // blood + PreCacheRange(1710,1715); + PreCacheRange(2410,2425); + PreCacheRange(389,389); // blood puddle by itself in art file + PreCacheRange(2500,2503); + // shrap + PreCacheRange(3840,3911); + PreCacheRange(3924,3947); + PreCacheRange(1397,1398); + // water *** animated tiles, can be deleted now *** + // PreCacheRange(780,794); + // switches + PreCacheRange(561,584); + PreCacheRange(551,552); + PreCacheRange(1846,1847); + PreCacheRange(1850,1859); + // bullet smoke + PreCacheRange(1748,1753); + // small blue font + PreCacheRange(2930,3023); + // gas can + PreCacheRange(3038,3042); + // lava *** animated tiles, can be deleted now *** + // PreCacheRange(175,182); + // gas clouds & teleport effect + PreCacheRange(3240,3277); + // nuke mushroom cloud + PreCacheRange(3280,3300); + // blood drops + PreCacheRange(1718,1721); + // smoke + PreCacheRange(3948,3968); + // footprints + PreCacheRange(2490,2492); + // player fists + PreCacheRange(4070,4077); + PreCacheRange(4050,4051); + PreCacheRange(4090,4093); + // fish actor + PreCacheRange(3760,3771); + PreCacheRange(3780,3795); + // coins + PreCacheRange(2531,2533); + // respawn markers & console keys + PreCacheRange(2440,2467); + // light/torch sprites + PreCacheRange(537,548); + PreCacheRange(521,528); + PreCacheRange(512,515); + PreCacheRange(396,399); + PreCacheRange(443,446); + // bubbles + PreCacheRange(716,720); + // bullet splashes + PreCacheRange(772,776); + } +} + +VOID PreCacheRipper(VOID) +{ + PreCacheSoundList(Ripper_SCTable, SIZ(Ripper_SCTable)); + PreCacheRange(1580, 1644); +} + +VOID PreCacheRipper2(VOID) +{ + PreCacheSoundList(Ripper2_SCTable, SIZ(Ripper2_SCTable)); + PreCacheRange(4320, 4427); +} + +VOID PreCacheCoolie(VOID) +{ + PreCacheGhost(); + PreCacheSoundList(Coolie_SCTable, SIZ(Coolie_SCTable)); + PreCacheRange(1400, 1440); + PreCacheRange(4260, 4276); // coolie explode +} + +VOID PreCacheGhost(VOID) +{ + PreCacheSoundList(Ghost_SCTable, SIZ(Ghost_SCTable)); + PreCacheRange(4277, 4312); +} + +VOID PreCacheSerpent(VOID) +{ + PreCacheSoundList(Serpent_SCTable, SIZ(Serpent_SCTable)); + PreCacheRange(960, 1016); + PreCacheRange(1300, 1314); +} + +VOID PreCacheGuardian(VOID) +{ + PreCacheSoundList(Guardian_SCTable, SIZ(Guardian_SCTable)); + PreCacheRange(1469,1497); +} + +VOID PreCacheNinja(VOID) +{ + PreCacheSoundList(Ninja_SCTable, SIZ(Ninja_SCTable)); + PreCacheRange(4096, 4239); +} + +VOID PreCacheNinjaGirl(VOID) +{ + //PreCacheSoundList(NinjaGirl_SCTable, SIZ(NinjaGirl_SCTable)); + PreCacheRange(5162, 5260); +} + +VOID PreCacheSumo(VOID) +{ + PreCacheSoundList(Sumo_SCTable, SIZ(Sumo_SCTable)); + PreCacheRange(4490, 4544); +} + +VOID PreCacheZilla(VOID) +{ + PreCacheSoundList(Sumo_SCTable, SIZ(Sumo_SCTable)); + PreCacheRange(4490, 4544); +} + +VOID PreCacheEel(VOID) +{ + PreCacheRange(4430, 4479); +} + +VOID PreCacheToiletGirl(VOID) +{ + PreCacheSoundList(Toilet_SCTable, SIZ(Toilet_SCTable)); + PreCacheRange(5023, 5027); +} + +VOID PreCacheWashGirl(VOID) +{ + PreCacheSoundList(Toilet_SCTable, SIZ(Toilet_SCTable)); + PreCacheRange(5032, 5035); +} + +VOID PreCacheCarGirl(VOID) +{ + PreCacheSoundList(Toilet_SCTable, SIZ(Toilet_SCTable)); + PreCacheRange(4594,4597); +} + +VOID PreCacheMechanicGirl(VOID) +{ + PreCacheSoundList(Toilet_SCTable, SIZ(Toilet_SCTable)); + PreCacheRange(4590,4593); +} + +VOID PreCacheSailorGirl(VOID) +{ + PreCacheSoundList(Toilet_SCTable, SIZ(Toilet_SCTable)); + PreCacheRange(4600,4602); +} + +VOID PreCachePruneGirl(VOID) +{ + PreCacheSoundList(Toilet_SCTable, SIZ(Toilet_SCTable)); + PreCacheRange(4604,4604); +} + +VOID PreCacheTrash(VOID) +{ + PreCacheSoundList(Trash_SCTable, SIZ(Trash_SCTable)); + PreCacheRange(2540, 2546); +} + +VOID PreCacheBunny(VOID) +{ + PreCacheSoundList(Bunny_SCTable, SIZ(Bunny_SCTable)); + PreCacheRange(4550, 4584); +} + +VOID PreCacheSkel(VOID) +{ + PreCacheRange(1320, 1396); +} + +VOID PreCacheHornet(VOID) +{ + PreCacheSoundList(Hornet_SCTable, SIZ(Hornet_SCTable)); + PreCacheRange(800, 811); +} + +VOID PreCacheSkull(VOID) +{ + PreCacheSoundList(Head_SCTable, SIZ(Head_SCTable)); + PreCacheRange(820, 854); +} + +VOID PreCacheBetty(VOID) +{ + PreCacheRange(817, 819); +} + +VOID PreCachePachinko(VOID) +{ + PreCacheRange(618,623); + PreCacheRange(618,623); + PreCacheRange(4768,4790); + PreCacheRange(4792,4814); + PreCacheRange(4816,4838); + PreCacheRange(4840,4863); + PreCacheSoundList(Pachinko_SCTable, SIZ(Pachinko_SCTable)); +} + +void PreCacheSoundList(short table[], int num) +{ + short j; + + for (j = 0; j < num; j++) + { + CacheSound(table[j], CACHE_SOUND_PRECACHE); + AnimateCacheCursor(); + } +} + +void +PreCacheTable(short table[], int num) +{ + short j; + + for (j = 0; j < num; j++) + { + SET(gotpic[table[j]>>3], 1<<(table[j]&7)); + } +} + +void +PreCacheRange(short start_pic, short end_pic) +{ + short j; + + for (j = start_pic; j <= end_pic; j++) + { + SET(gotpic[j>>3], 1<<(j&7)); + } +} + +VOID PreCacheAmbient(VOID) +{ + int i,nexti; + int num; + SPRITEp sp; + extern AMB_INFO ambarray[]; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_AMBIENT], i, nexti) + { + sp = &sprite[i]; + + num = sp->lotag; + num = ambarray[num].diginame; + + CacheSound(num, CACHE_SOUND_PRECACHE); + } +} + +VOID PreCacheOverride(VOID) +{ + int i,nexti; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], i, nexti) + { + ASSERT(SPRITE_TAG2(i) >= 0 && SPRITE_TAG2(i) <= MAXTILES); + SET_GOTPIC(SPRITE_TAG2(i)); + } +} + + +VOID PreCacheSoundSpot(VOID) +{ + int i,nexti; + int num; + SPRITEp sp; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_SOUND_SPOT], i, nexti) + { + sp = &sprite[i]; + + num = SP_TAG13(sp); // tag4 is copied to tag13 + if (num > 0 && num < DIGI_MAX) + CacheSound(num, CACHE_SOUND_PRECACHE); + + num = SP_TAG5(sp); + if (num > 0 && num < DIGI_MAX) + CacheSound(num, CACHE_SOUND_PRECACHE); + + num = SP_TAG6(sp); + if (num > 0 && num < DIGI_MAX) + CacheSound(num, CACHE_SOUND_PRECACHE); + + CacheSound(num, CACHE_SOUND_PRECACHE); + } +} + +VOID +PreCacheActor(VOID) +{ + int i; + short pic; + + for (i=0; i < MAXSPRITES; i++) + { + if (sprite[i].statnum >= MAXSTATUS) + continue; + + if (User[i]) + pic = User[i]->ID; + else + pic = sprite[i].picnum; + + switch (pic) + { + case COOLIE_RUN_R0: + PreCacheCoolie(); + break; + + case NINJA_RUN_R0: + case NINJA_CRAWL_R0: + PreCacheNinja(); + break; + + case GORO_RUN_R0: + PreCacheGuardian(); + break; + + case 1441: + case COOLG_RUN_R0: + PreCacheGhost(); + break; + + case EEL_RUN_R0: + PreCacheEel(); + break; + + case SUMO_RUN_R0: + PreCacheZilla(); + break; + + case ZILLA_RUN_R0: + PreCacheSumo(); + break; + + case TOILETGIRL_R0: + PreCacheToiletGirl(); + break; + + case WASHGIRL_R0: + PreCacheWashGirl(); + break; + + case CARGIRL_R0: + PreCacheCarGirl(); + break; + + case MECHANICGIRL_R0: + PreCacheMechanicGirl(); + break; + + case SAILORGIRL_R0: + PreCacheSailorGirl(); + break; + + case PRUNEGIRL_R0: + PreCachePruneGirl(); + break; + + case TRASHCAN: + PreCacheTrash(); + break; + + case BUNNY_RUN_R0: + PreCacheBunny(); + break; + + case RIPPER_RUN_R0: + PreCacheRipper(); + break; + + case RIPPER2_RUN_R0: + PreCacheRipper2(); + break; + + case SERP_RUN_R0: + PreCacheSerpent(); + break; + + case LAVA_RUN_R0: + break; + + case SKEL_RUN_R0: + PreCacheSkel(); + break; + + case HORNET_RUN_R0: + PreCacheHornet(); + break; + + case SKULL_R0: + PreCacheSkull(); + break; + + case BETTY_R0: + PreCacheBetty(); + break; + + case GIRLNINJA_RUN_R0: + PreCacheNinjaGirl(); + break; + + case 623: // Pachinko win light + case PACHINKO1: + case PACHINKO2: + case PACHINKO3: + case PACHINKO4: + PreCachePachinko(); + break; + } + } +} + + +void DoTheCache(void) +{ + extern char CacheLastLevel[32],LevelName[20]; + int i, cnt=0; + + PreCacheAmbient(); + PreCacheSoundSpot(); + PreCacheActor(); + PreCacheOverride(); + + for (i = 0; i < MAXTILES; i++) + { + if ((TEST(gotpic[i>>3], 1<<(i&7))) && (!waloff[i])) + { + loadtile(i); + cnt++; + if (!(cnt&7)) + { + AnimateCacheCursor(); + handleevents(); + getpackets(); + } + } + } + + memset(gotpic,0,sizeof(gotpic)); + strcpy(CacheLastLevel, LevelName); +} + +void +precache(void) +{ + int i; + short j; + SECTORp sectp; + WALLp wp; + SPRITEp sp; + + memset(gotpic,0,sizeof(gotpic)); + + for (sectp = sector; sectp < §or[numsectors]; sectp++) + { + j = sectp->ceilingpicnum; + + SET(gotpic[j>>3], 1<<(j&7)); + + if (TEST(picanm[j],TILE_ANIM_TYPE)) + { + for (i = 1; i <= TEST(picanm[j],TILE_ANIM_NUM); i++) + { + SET(gotpic[(j+i)>>3], 1<<((j+i)&7)); + } + } + + j = sectp->floorpicnum; + + SET(gotpic[j>>3], 1<<(j&7)); + + if (TEST(picanm[j],TILE_ANIM_TYPE)) + { + for (i = 1; i <= TEST(picanm[j],TILE_ANIM_NUM); i++) + { + SET(gotpic[(j+i)>>3], 1<<((j+i)&7)); + } + } + + } + + for (wp = wall; wp < &wall[numwalls]; wp++) + { + j = wp->picnum; + + SET(gotpic[j>>3], 1<<(j&7)); + + if (TEST(picanm[j],TILE_ANIM_TYPE)) + { + for (i = 1; i <= TEST(picanm[j],TILE_ANIM_NUM); i++) + { + SET(gotpic[(j+i)>>3], 1<<((j+i)&7)); + } + } + + if (wp->overpicnum > 0 && wp->overpicnum < MAXTILES) + { + j = wp->overpicnum; + SET(gotpic[j>>3], 1<<(j&7)); + + if (TEST(picanm[j],TILE_ANIM_TYPE)) + { + for (i = 1; i <= TEST(picanm[j],TILE_ANIM_NUM); i++) + { + SET(gotpic[(j+i)>>3], 1<<((j+i)&7)); + } + } + + } + } + + for (sp = sprite; sp < &sprite[MAXSPRITES]; sp++) + { + if (sp->statnum < MAXSTATUS) + { + j = sp->picnum; + + SET(gotpic[j>>3], 1<<(j&7)); + } + } +} + + diff --git a/polymer/eduke32/source/sw/src/cache.h b/polymer/eduke32/source/sw/src/cache.h new file mode 100644 index 000000000..3e784326c --- /dev/null +++ b/polymer/eduke32/source/sw/src/cache.h @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#define CACHE_NONE 0 // don't use this - this is for ken +#define CACHE_LOCK_MAX 255 +#define CACHE_LOCK_START 200 +#define CACHE_UNLOCK_START 1 +#define CACHE_UNLOCK_MAX 199 + +#define CACHE_SOUND_PRECACHE 0 +#define CACHE_SOUND_PLAY 1 + +void SetupPreCache(void); +void PreCacheRange(short start_pic, short end_pic); +void DoTheCache(void); +void precache(void); + diff --git a/polymer/eduke32/source/sw/src/cheats.c b/polymer/eduke32/source/sw/src/cheats.c new file mode 100644 index 000000000..0a297edab --- /dev/null +++ b/polymer/eduke32/source/sw/src/cheats.c @@ -0,0 +1,470 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "mytypes.h" +#include "text.h" + +#include "control.h" +#include "function.h" +//#include "inv.h" + + +BOOL CheatInputMode = FALSE; +char CheatInputString[256]; +BOOL EveryCheat = FALSE; +BOOL ResCheat = FALSE; + +VOID ResCheatOn(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + ResCheat = TRUE; +} + +VOID VoxCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + //gs.Voxel ^= 1; +} + +VOID RestartCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + ExitLevel = TRUE; +} + +VOID RoomCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + extern BOOL FAF_DebugView; + FAF_DebugView ^= 1; +} + +VOID SecretCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + gs.Stats = !gs.Stats; +} + +VOID NextCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + Level++; + ExitLevel = TRUE; +} + +VOID PrevCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + Level--; + ExitLevel = TRUE; +} + +VOID MapCheat(PLAYERp pp, char *UNUSED(cheat_string)) +{ + automapping ^= 1; + + if (automapping) + MapSetAll2D(0); + else + MapSetAll2D(0xFF); + + sprintf(ds, "AUTOMAPPING %s", automapping ? "ON" : "OFF"); + PutStringInfo(pp, ds); +} + + +VOID LocCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + extern BOOL LocationInfo; + LocationInfo++; + if (LocationInfo > 2) + LocationInfo = 0; +} + + +VOID WeaponCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string)) +{ + PLAYERp p; + short pnum; + unsigned int i; + USERp u; + + TRAVERSE_CONNECT(pnum) + { + p = &Player[pnum]; + u = User[p->PlayerSprite]; + + // ALL WEAPONS + if (!SW_SHAREWARE) + p->WpnFlags = 0xFFFFFFFF; + else + p->WpnFlags = 0x0000207F; // Disallows high weapon cheat in shareware + + for (i = 0; i < SIZ(p->WpnAmmo); i++) + { + p->WpnAmmo[i] = DamageData[i].max_ammo; + } + + PlayerUpdateWeapon(p, u->WeaponNum); + } +} + + +VOID GodCheat(PLAYERp pp, char *UNUSED(cheat_string)) +{ + // + // GOD mode + // + GodMode ^= 1; + + sprintf(ds, "GOD MODE %s", GodMode ? "ON" : "OFF"); + PutStringInfo(pp, ds); +} + +VOID ClipCheat(PLAYERp pp, char *UNUSED(cheat_string)) +{ + FLIP(pp->Flags, PF_CLIP_CHEAT); + + sprintf(ds, "NO CLIP MODE %s", TEST(pp->Flags, PF_CLIP_CHEAT) ? "ON" : "OFF"); + PutStringInfo(pp, ds); +} + +VOID WarpCheat(PLAYERp pp, char *cheat_string) +{ + char *cp = cheat_string; + int episode_num; + int level_num; + + cp += sizeof("swtrek")-1; + level_num = atol(cp); + + //DSPRINTF(ds,"ep %d, lev %d",episode_num, level_num); + //MONO_PRINT(ds); + + if (!SW_SHAREWARE) + { + if (level_num > 28 || level_num < 1) + return; + } + else + { + if (level_num > 4 || level_num < 1) + return; + } + + Level = level_num; + ExitLevel = TRUE; + + sprintf(ds, "ENTERING %1d", Level); + PutStringInfo(pp, ds); +} + +VOID ItemCheat(PLAYERp pp, char *cheat_string) +{ + // + // Get all ITEMS + // + PLAYERp p; + short pnum; + short inv; + int i; + + PutStringInfo(pp, "ITEMS"); + + TRAVERSE_CONNECT(pnum) + { + p = &Player[pnum]; + memset(p->HasKey, TRUE, sizeof(p->HasKey)); + + if (p->Wpn[WPN_UZI] && p->CurWpn == p->Wpn[WPN_UZI]) + { + SET(p->Flags, PF_TWO_UZI); + SET(p->Flags, PF_PICKED_UP_AN_UZI); + InitWeaponUzi(p); + } + + p->WpnShotgunAuto = 50; + p->WpnRocketHeat = 5; + p->WpnRocketNuke = 1; + p->Armor = 100; + + for (inv = 0; inv < MAX_INVENTORY; inv++) + { + p->InventoryPercent[inv] = 100; + //p->InventoryAmount[inv] = 1; + p->InventoryAmount[inv] = InventoryData[inv].MaxInv; + //PlayerUpdateInventory(p, inv); + } + + PlayerUpdateInventory(p, p->InventoryNum); + //p->InventoryNum = 0; + } + + for (i=0; istag == SECT_LOCK_DOOR) + SectUser[i]->number = 0; // unlock all doors of this type + } + + WeaponCheat(pp, cheat_string); + PlayerUpdateKeys(pp); +} + +VOID EveryCheatToggle(PLAYERp pp, char *cheat_string) +{ + EveryCheat ^= 1; + + WeaponCheat(pp, cheat_string); + GodCheat(pp, cheat_string); + ItemCheat(pp, cheat_string); + + sprintf(ds, "EVERY CHEAT %s", EveryCheat ? "ON" : "OFF"); + PutStringInfo(pp, ds); +} + +VOID SaveCheat(PLAYERp pp, char *UNUSED(cheat_string)) +{ + saveboard("swsave.map", &pp->posx, &pp->posy, &pp->posz, + &pp->pang, &pp->cursectnum); +} + +VOID GeorgeFunc(PLAYERp pp, char *UNUSED(cheat_string)) +{ + PlayerSound(DIGI_TAUNTAI9,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_doppler|v3df_follow,pp); +} + +VOID BlackburnFunc(PLAYERp pp, char *UNUSED(cheat_string)) +{ + PlayerSound(DIGI_TAUNTAI3,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_doppler|v3df_follow,pp); +} + +int cheatcmp(char *str1, char *str2, int len) +{ + char *cp1 = str1; + char *cp2 = str2; + + do + { + if (*cp1 != *cp2) + { + if (!((*cp1 == '#' && isdigit(*cp2)) || (*cp2 == '#' && isdigit(*cp1)))) + return -1; + } + + cp1++; + cp2++; + } + while (--len); + + return 0; +} + + +#define CF_ALL BIT(0) +#define CF_NOTSW BIT(1) + +typedef struct +{ + char *CheatInputCode; + void (*CheatInputFunc)(PLAYERp, char *); + char flags; +} CHEAT_INFO, *CHEAT_INFOp; + + +CHEAT_INFO ci[] = +{ + {"swchan", GodCheat, 0}, + {"swgimme", ItemCheat, 0}, + {"swtrek##", WarpCheat, 0}, + {"swgreed", EveryCheatToggle, 0}, + {"swghost", ClipCheat, 0}, + + {"swstart", RestartCheat, 0}, + + {"swres", ResCheatOn, 0}, + {"swloc", LocCheat, 0}, + {"swmap", MapCheat, 0}, + {"swsave", SaveCheat, CF_ALL}, + {"swroom", RoomCheat, CF_NOTSW}, // Room above room dbug +#if DEBUG + {"swsecret", SecretCheat, CF_ALL}, +#endif +}; + + +// !JIM! My simplified version of CheatInput which simply processes MessageInputString +void CheatInput(void) +{ + static BOOL cur_show; + int ret; + BOOL match = FALSE; + unsigned int i; + + //if (CommEnabled) + // return; + + strcpy(CheatInputString,MessageInputString); + + // make sure string is lower cased + Bstrlwr(CheatInputString); + + // check for at least one single match + for (i = 0; i < SIZ(ci); i++) + { + // compare without the NULL + if (cheatcmp(CheatInputString, ci[i].CheatInputCode, strlen(CheatInputString)) == 0) + { + + // if they are equal in length then its a complet match + if (strlen(CheatInputString) == strlen(ci[i].CheatInputCode)) + { + match = TRUE; + CheatInputMode = FALSE; + + if (TEST(ci[i].flags, CF_NOTSW) && SW_SHAREWARE) + return; + + if (!TEST(ci[i].flags, CF_ALL)) + { + if (CommEnabled) + return; + + if (Skill >= 3) + { + PutStringInfo(Player, "You're too skillful to cheat\n"); + return; + } + } + + if (ci[i].CheatInputFunc) + (*ci[i].CheatInputFunc)(Player, CheatInputString); + + return; + } + else + { + match = TRUE; + break; + } + } + } + + if (!match) + { + ////DSPRINTF(ds,"Lost A Match %s", CheatInputString); + //MONO_PRINT(ds); + + CheatInputMode = FALSE; + } +} + +/* OLD CODE +void CheatInput(void) + { + static BOOL cur_show; + signed char MNU_InputString(char *, short); + int ret; + BOOL match = FALSE; + short i; + + // don't use InputMode here - its set for CheatInputMode + if (MessageInputMode || MenuInputMode) + return; + + if (!CheatInputMode) + { + if (KEY_PRESSED(KEYSC_S)) + { + //KEY_PRESSED(KEYSC_S) = FALSE; + CheatInputMode = TRUE; + strcpy(CheatInputString,"s"); + } + } + + if (CheatInputMode) + { + // get new chars + ret = MNU_InputString(CheatInputString, 320-20); + + // quick check input + switch (ret) + { + case FALSE: // Input finished (RETURN) + case -1: // Cancel Input (pressed ESC) or Err + CheatInputMode = FALSE; + KB_FlushKeyboardQueue(); + return; + + case TRUE: // Got input + break; + } + + // make sure string is lower cased + strlwr(CheatInputString); + + // check for at least one single match + for (i = 0; i < SIZ(ci); i++) + { + // compare without the NULL + if (cheatcmp(CheatInputString, ci[i].CheatInputCode, strlen(CheatInputString)) == 0) + { + ////DSPRINTF(ds,"%s",CheatInputString); + //MONO_PRINT(ds); + + // if they are equal in length then its a complet match + if (strlen(CheatInputString) == strlen(ci[i].CheatInputCode)) + { + ////DSPRINTF(ds,"Found A Match %s", CheatInputString); + //MONO_PRINT(ds); + + match = TRUE; + + CheatInputMode = FALSE; + KB_FlushKeyboardQueue(); + + if (ci[i].CheatInputFunc) + (*ci[i].CheatInputFunc)(Player, CheatInputString); + + return; + } + else + { + match = TRUE; + break; + } + } + } + + if (!match) + { + ////DSPRINTF(ds,"Lost A Match %s", CheatInputString); + //MONO_PRINT(ds); + + CheatInputMode = FALSE; + KB_FlushKeyboardQueue(); + } + } + } + +*/ diff --git a/polymer/eduke32/source/sw/src/colormap.c b/polymer/eduke32/source/sw/src/colormap.c new file mode 100644 index 000000000..f83d7f9f5 --- /dev/null +++ b/polymer/eduke32/source/sw/src/colormap.c @@ -0,0 +1,466 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "pal.h" +#include "game.h" + +short f_c = 3; +static unsigned char tempbuf[256]; +unsigned char DefaultPalette[256 * 32]; +#if 1 +VOID +MapColors(short num, COLOR_MAP cm, short create) +{ + int i; + float inc; + + if (create) + { + for (i = 0; i < 256; i++) + tempbuf[i] = i; + } + + if (cm.FromRange == 0 || num <= 0 || num >= 256) + { + return; + } + + inc = cm.ToRange/((float)cm.FromRange); + + for (i = 0; i < cm.FromRange; i++) + tempbuf[i + cm.FromColor] = (i*inc) + cm.ToColor; +} +#else +VOID +MapColors(short num, COLOR_MAP cm, short create) +{ + int i; + + if (create) + { + for (i = 0; i < 256; i++) + tempbuf[i] = i; + } + + if (cm.FromRange == 0 || num <= 0 || num >= 256) + { + return; + } + + // from 32 to 32 || 16 to 16 + if (cm.ToRange == cm.FromRange) + { + for (i = 0; i < cm.FromRange; i++) + tempbuf[i + cm.FromColor] = i + cm.ToColor; + + // Quick fix for grey + if (cm.ToColor == LT_GREY) + tempbuf[cm.FromColor+31] = 0; // Set to black + } + else + // from 32 to 16 + if (cm.ToRange == DIV2(cm.FromRange)) + { + for (i = 0; i < cm.FromRange; i++) + tempbuf[cm.FromColor + i] = cm.ToColor + DIV2(i); + } + else + // from 16 to 32 + if (DIV2(cm.ToRange) == cm.FromRange) + { + for (i = 0; i < cm.FromRange; i++) + tempbuf[cm.FromColor + DIV2(i)] = cm.ToColor; + + // Quick fix for grey + if (cm.ToColor == LT_GREY) + tempbuf[cm.FromColor+31] = 0; // Set to black + } +} +#endif + +#define PLAYER_COLOR_MAPS 15 +static COLOR_MAP PlayerColorMap[PLAYER_COLOR_MAPS][1] = +{ + + { + {32, 32, LT_BLUE, LT_BROWN}, + }, + { + {32, 31, LT_BLUE, LT_GREY}, + }, + { + {32, 16, LT_BLUE, PURPLE} + }, + { + {32, 16, LT_BLUE, RUST_RED}, + }, + { + {32, 16, LT_BLUE, YELLOW}, + }, + { + {32, 16, LT_BLUE, DK_GREEN}, + }, + { + {32, 16, LT_BLUE, GREEN}, + }, + { + {32, 32, LT_BLUE, LT_BLUE}, // Redundant, but has to be here for position + }, + { + {32, 32, LT_BLUE, LT_TAN}, + }, + { + {32, 16, LT_BLUE, RED}, + }, + { + {32, 16, LT_BLUE, DK_GREY}, + }, + { + {32, 16, LT_BLUE, BRIGHT_GREEN}, + }, + { + {32, 16, LT_BLUE, DK_BLUE}, + }, + { + {32, 16, LT_BLUE, FIRE}, + }, + { + {32, 16, LT_BLUE, FIRE}, + } + +}; + +VOID +InitPalette(VOID) +{ + static COLOR_MAP AllToRed[] = + { + {31, 16, LT_GREY, RED}, + {32, 16, LT_BROWN, RED}, + {32, 16, LT_TAN, RED}, + {16, 16, RUST_RED, RED}, + {16, 16, YELLOW, RED}, + {16, 16, BRIGHT_GREEN, RED}, + {16, 16, DK_GREEN, RED}, + {16, 16, GREEN, RED}, + {32, 16, LT_BLUE, RED}, + {16, 16, PURPLE, RED}, + {16, 16, FIRE, RED} + }; + + static COLOR_MAP AllToBlue[] = + { + {31, 32, LT_GREY, LT_BLUE}, + {32, 32, LT_BROWN, LT_BLUE}, + {32, 32, LT_TAN, LT_BLUE}, + {16, 32, RUST_RED, LT_BLUE}, + {16, 32, YELLOW, LT_BLUE}, + {16, 32, BRIGHT_GREEN, LT_BLUE}, + {16, 32, DK_GREEN, LT_BLUE}, + {16, 32, GREEN, LT_BLUE}, + {16, 32, RED, LT_BLUE}, + {16, 32, PURPLE, LT_BLUE}, + {16, 32, FIRE, LT_BLUE} + }; + + static COLOR_MAP AllToGreen[] = + { + {31, 16, LT_GREY, GREEN}, + {32, 16, LT_BROWN, GREEN}, + {32, 16, LT_TAN, GREEN}, + {16, 16, RUST_RED, GREEN}, + {16, 16, YELLOW, GREEN}, + {16, 16, BRIGHT_GREEN, GREEN}, + {16, 16, DK_GREEN, GREEN}, + {16, 16, GREEN, GREEN}, + {32, 16, LT_BLUE, GREEN}, + {16, 16, RED, GREEN}, + {16, 16, PURPLE, GREEN}, + {16, 16, FIRE, GREEN} + }; + + static COLOR_MAP NinjaBasic[] = + { + {32, 16, LT_TAN, DK_GREY}, + {32, 16, LT_BROWN,DK_GREY}, + {32, 31, LT_BLUE,LT_GREY}, + {16, 16, DK_GREEN,DK_GREY}, + {16, 16, GREEN, DK_GREY}, + {16, 16, YELLOW, DK_GREY} + }; + + static COLOR_MAP NinjaRed[] = + { + {16, 16, DK_TAN, DK_GREY}, + {16, 16, GREEN, DK_TAN}, + {16, 8, DK_BROWN, RED + 8}, + + {32, 16, LT_BLUE, RED} + }; + + static COLOR_MAP NinjaGreen[] = + { + {16, 16, DK_TAN, DK_GREY}, + {16, 16, GREEN, DK_TAN}, + {16, 8, DK_BROWN, GREEN + 6}, + + {32, 16, LT_BLUE, GREEN} + }; + + static COLOR_MAP Illuminate[] = + { + {16, 8, LT_GREY, BRIGHT_GREEN}, + {16, 8, DK_GREY, BRIGHT_GREEN}, + {16, 8, LT_BROWN, BRIGHT_GREEN}, + {16, 8, DK_BROWN, BRIGHT_GREEN}, + {16, 8, LT_TAN, BRIGHT_GREEN}, + {16, 8, DK_TAN, BRIGHT_GREEN}, + {16, 8, RUST_RED, BRIGHT_GREEN}, + {16, 8, YELLOW, BRIGHT_GREEN}, + {16, 8, DK_GREEN, BRIGHT_GREEN}, + {16, 8, GREEN, BRIGHT_GREEN}, + {32, 8, LT_BLUE, BRIGHT_GREEN}, + {16, 8, RED, BRIGHT_GREEN}, + {16, 8, PURPLE, BRIGHT_GREEN}, + {16, 8, FIRE, BRIGHT_GREEN} + }; + + static COLOR_MAP BrownRipper = {31, 32, LT_GREY, LT_TAN}; + + static COLOR_MAP SkelGore = {16, 16, RED, BRIGHT_GREEN}; + static COLOR_MAP ElectroGore = {16, 16, RED, DK_BLUE}; + + static COLOR_MAP MenuHighlight = {16, 16, RED, FIRE}; + + unsigned int i; + short play; + +#if 0 + // I need this for doing fog... Not sure why it wasn't already here. + initfastcolorlookup(1,1,1); +#endif + + // + // Save default palette + // + + memcpy(DefaultPalette, palookup[PALETTE_DEFAULT], 256 * 32); + + // + // Dive palettes + // + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + // palette for underwater + makepalookup(PALETTE_DIVE, tempbuf, 0, 0, 15, TRUE); + +#define FOG_AMT 15 + for (i = 0; i < 256; i++) + tempbuf[i] = i; + makepalookup(PALETTE_FOG, tempbuf, FOG_AMT, FOG_AMT, FOG_AMT, TRUE); + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + makepalookup(PALETTE_DIVE_LAVA, tempbuf, 11, 0, 0, TRUE); + + // + // 1 Range changes + // + + MapColors(PALETTE_BROWN_RIPPER, BrownRipper, TRUE); + makepalookup(PALETTE_BROWN_RIPPER, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_SKEL_GORE, SkelGore, TRUE); + makepalookup(PALETTE_SKEL_GORE, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_ELECTRO_GORE, ElectroGore, TRUE); + makepalookup(PALETTE_ELECTRO_GORE, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_MENU_HIGHLIGHT, MenuHighlight, TRUE); + makepalookup(PALETTE_MENU_HIGHLIGHT, tempbuf, 0, 0, 0, TRUE); + + // + // Multiple range changes + // + + MapColors(PALETTE_BASIC_NINJA, NinjaBasic[0], TRUE); + for (i = 1; i < SIZ(NinjaBasic); i++) + MapColors(PALETTE_BASIC_NINJA, NinjaBasic[i], FALSE); + makepalookup(PALETTE_BASIC_NINJA, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_RED_NINJA, NinjaRed[0], TRUE); + for (i = 1; i < SIZ(NinjaRed); i++) + MapColors(PALETTE_RED_NINJA, NinjaRed[i], FALSE); + makepalookup(PALETTE_RED_NINJA, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_GREEN_NINJA, NinjaGreen[0], TRUE); + for (i = 1; i < SIZ(NinjaGreen); i++) + MapColors(PALETTE_GREEN_NINJA, NinjaGreen[i], FALSE); + makepalookup(PALETTE_GREEN_NINJA, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_GREEN_LIGHTING, AllToGreen[0], TRUE); + for (i = 1; i < SIZ(AllToGreen); i++) + MapColors(PALETTE_GREEN_LIGHTING, AllToGreen[i], FALSE); + makepalookup(PALETTE_GREEN_LIGHTING, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_RED_LIGHTING, AllToRed[0], TRUE); + for (i = 1; i < SIZ(AllToRed); i++) + MapColors(PALETTE_RED_LIGHTING, AllToRed[i], FALSE); + makepalookup(PALETTE_RED_LIGHTING, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_BLUE_LIGHTING, AllToBlue[0], TRUE); + for (i = 1; i < SIZ(AllToBlue); i++) + MapColors(PALETTE_BLUE_LIGHTING, AllToBlue[i], FALSE); + makepalookup(PALETTE_BLUE_LIGHTING, tempbuf, 0, 0, 0, TRUE); + + MapColors(PALETTE_ILLUMINATE, Illuminate[0], TRUE); + for (i = 1; i < SIZ(Illuminate); i++) + MapColors(PALETTE_ILLUMINATE, Illuminate[i], FALSE); + makepalookup(PALETTE_ILLUMINATE, tempbuf, 0, 0, 0, TRUE); + + // PLAYER COLORS - ALSO USED FOR OTHER THINGS + for (play = 0; play < PLAYER_COLOR_MAPS; play++) + { + MapColors(PALETTE_PLAYER0 + play, PlayerColorMap[play][0], TRUE); + MapColors(PALETTE_PLAYER0 + play, PlayerColorMap[play][0], FALSE); + makepalookup(PALETTE_PLAYER0 + play, tempbuf, 0, 0, 0, TRUE); + } + + // + // Special Brown sludge + // + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + // invert the brown palette + for (i = 0; i < 32; i++) + tempbuf[LT_BROWN + i] = (LT_BROWN + 32) - i; + makepalookup(PALETTE_SLUDGE, tempbuf, 0, 0, 0, TRUE); + +} + + +/* +2. You must now use my function to set or get any palette + registers.This means that the keywords "3c7", "3c8", and "3c9" should not even exist in your code.I really + didn 't want to force you to use my palette functions, but + since VESA 2.0 supports non VGA compatible cards, you must +do + it this way.If you use setbrightness for all of your + palette setting, then you can ignore this.Note that the + palette format here is VESA 's palette format, which is + different than my other palette control functions.It 's + 4 bytes and RGB are backwards.Here are the function + prototypes: + + VBE_setPalette(long palstart, long palnum, char *dapal); + +VBE_getPalette(long palstart, long palnum, char *dapal); +palstart is the offset of the first palette to set + palnum is the number of the palette entries to set + dapal is a pointer to the palette buffer.The palette + buffer must be in this format: +char Blue, Green, Red, reserved; +I think this format stinks, but since VESA 2.0 uses + it, the code will run fastest if the buffer is not + copied.You can make your own cover up function if + you don 't like this format. + + This example sets up a wasteful gray scale palette: + +char mypalette[1024]; + +for (i = 0; i < 256; i++) + { + mypalette[i * 4 + 0] = (i >> 2); // Blue + mypalette[i * 4 + 1] = (i >> 2); // Green + mypalette[i * 4 + 2] = (i >> 2); // Red + mypalette[i * 4 + 3] = 0; // reserved + } +VBE_setPalette(0, 256, mypalette); +*/ + +#define ORED 0 +#define OGREEN 1 +#define OBLUE 2 + +#define NBLUE 0 +#define NGREEN 1 +#define NRED 2 +#define NRESERVED 3 + +VOID SetPaletteToVESA(unsigned char *pal) +{ + /* + char pal_buff[1024]; + short i; + + for (i = 0; i < 256; i++) + { + pal_buff[i * 4 + NRED] = pal[i * 3 + ORED]; + pal_buff[i * 4 + NGREEN] = pal[i * 3 + OGREEN]; + pal_buff[i * 4 + NBLUE] = pal[i * 3 + OBLUE]; + pal_buff[i * 4 + NRESERVED] = 0; + } + + VBE_setPalette(0, 256, pal_buff); + */ + setbrightness(0,pal,4|2); + // fprintf(stderr,"SetPaletteToVESA() called\n"); +} + +VOID set_pal(unsigned char *pal) +{ + SetPaletteToVESA(pal); +} + +VOID GetPaletteFromVESA(unsigned char *pal) +{ + /* + char pal_buff[1024]; + short i; + + VBE_getPalette(0, 256, pal_buff); + + for (i = 0; i < 256; i++) + { + pal[i * 3 + ORED] = pal_buff[i * 4 + NRED]; + pal[i * 3 + OGREEN] = pal_buff[i * 4 + NGREEN]; + pal[i * 3 + OBLUE] = pal_buff[i * 4 + NBLUE]; + } + */ + int i; + for (i=0; i<256; i++) + { + pal[i*3+0] = curpalette[i].r>>2; + pal[i*3+1] = curpalette[i].g>>2; + pal[i*3+2] = curpalette[i].b>>2; + } + // fprintf(stderr,"GetPaletteFromVESA() called\n"); +} diff --git a/polymer/eduke32/source/sw/src/colormap.h b/polymer/eduke32/source/sw/src/colormap.h new file mode 100644 index 000000000..039d2bf47 --- /dev/null +++ b/polymer/eduke32/source/sw/src/colormap.h @@ -0,0 +1,6 @@ +void MapColors(short num,COLOR_MAP cm,short create); +void InitPalette(void); +void SetPaletteToVESA(unsigned char *pal); +void set_pal(unsigned char *pal); +void GetPaletteFromVESA(unsigned char *pal); +void InitPalette(void); diff --git a/polymer/eduke32/source/sw/src/common_game.h b/polymer/eduke32/source/sw/src/common_game.h new file mode 100644 index 000000000..0620ff416 --- /dev/null +++ b/polymer/eduke32/source/sw/src/common_game.h @@ -0,0 +1,137 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +//**************************************************************************** +// +// common_game.h +// +// common defines for the setup program +// +//**************************************************************************** + +#ifndef common_public_ +#define common_public_ +#ifdef __cplusplus +extern "C" { +#endif + +//**************************************************************************** +// +// DEFINES +// +//**************************************************************************** + +// +// Color Defines +// + +#define MENUBACK_FOREGROUND COLOR_BLACK +#define MENUBACK_BACKGROUND COLOR_DARKGRAY + +#define MENUBACKBORDER_FOREGROUND COLOR_BLACK +#define MENUBACKBORDER_BACKGROUND COLOR_GRAY + +#define MENU_ACTIVE_FOREGROUND COLOR_WHITE +#define MENU_INACTIVE_FOREGROUND COLOR_GRAY +#define MENU_DISPLAY_FOREGROUND COLOR_LIGHTGREEN + +#define MENU_SECTIONHEADER_FOREGROUND COLOR_YELLOW + +// +// Setup program defines +// + +#define SETUPFILENAME "sw.cfg" + +#define SETUPPROGRAMNAME ("Shadow Warrior Setup") +#define SETUPPROGRAMVERSION ("1.2") + +#define GAMENAME "Shadow Warrior" +#define GAMELAUNCHER ("SW.EXE") +#define GAMETOTYPE ("SW") + +#define MENUFOOTER "Esc Exits  Move ÄÙ Selects\0" + +#define COMMITLAUNCHER ("COMMIT.EXE") +#define COMMITFILENAME ("COMMIT.DAT") + +#define MAXVOICES 32 +#define SONGNAME ("Shadow Warrior Theme Song") +//#define SOUNDSETUPLAUNCHER ("SNDSETUP.EXE") + +// Default Socket Number + +#define DEFAULTSOCKETNUMBER 0x8849 + +// Default RTS file + +#define DEFAULTRTSFILE "sw.rts" + +// Default RTS path + +#define DEFAULTRTSPATH ".\\" + +// Default UserLevel path + +#define DEFAULTLEVELPATH ".\\" + +// Default External Control file + +#define DEFAULTCONTROLFILE "EXTERNAL.EXE" + +// Default Help file + +#define DEFAULTHELPFILE "SWHELP.EXE" + +// RTS extension + +#define RTSEXTENSION "RTS" + +// MAP extension + +#define MAPEXTENSION "MAP" + +// Default Player name + +#define DEFAULTPLAYERNAME "KATO" + +// Default Macros + +#define MACRO1 "Burn baby burn..." +#define MACRO2 "You make another stupid move." +#define MACRO3 "Blocking with your head again?" +#define MACRO4 "You not fight well with hands!" +#define MACRO5 "You so stupid!" +#define MACRO6 "Quit jerking off. Come fight me!" +#define MACRO7 "What the matter you scaredy cat?" +#define MACRO8 "Did I break your concentration?" +#define MACRO9 "Hope you were paying attention." +#define MACRO10 "ITTAIIIUUU!!!" + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/polymer/eduke32/source/sw/src/config.c b/polymer/eduke32/source/sw/src/config.c new file mode 100644 index 000000000..fdaef0b7f --- /dev/null +++ b/polymer/eduke32/source/sw/src/config.c @@ -0,0 +1,731 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" +#include "baselayer.h" +#include "osd.h" + +#include "settings.h" +#include "mytypes.h" +#include "develop.h" +#include "scriplib.h" +#include "file_lib.h" +#include "gamedefs.h" +#include "keyboard.h" +#include "util_lib.h" +#include "function.h" +#include "control.h" +#include "fx_man.h" +#include "sounds.h" +#include "config.h" +#include "common_game.h" + +// we load this in to get default button and key assignments +// as well as setting up function mappings + +#include "_functio.h" +#include "_config.h" + +extern void ReadGameSetup(int32 scripthandle); +extern void WriteGameSetup(int32 scripthandle); + +// +// Comm variables +// + +char CommPlayerName[32]; +int32 NumberPlayers,CommPort,PortSpeed,IrqNumber,UartAddress; + +// +// Sound variables +// +int32 FXDevice = 0; +int32 MusicDevice = 0; +int32 NumVoices = 32; +int32 NumChannels = 2; +int32 NumBits = 16; +int32 MixRate = 44100; + +int32 UseMouse = 1, UseJoystick = 0; + +byte KeyboardKeys[NUMGAMEFUNCTIONS][2]; +int32 MouseButtons[MAXMOUSEBUTTONS]; +int32 MouseButtonsClicked[MAXMOUSEBUTTONS]; +int32 MouseDigitalAxes[MAXMOUSEAXES][2]; +int32 MouseAnalogAxes[MAXMOUSEAXES]; +int32 MouseAnalogScale[MAXMOUSEAXES]; +int32 JoystickButtons[MAXJOYBUTTONS]; +int32 JoystickButtonsClicked[MAXJOYBUTTONS]; +int32 JoystickDigitalAxes[MAXJOYAXES][2]; +int32 JoystickAnalogAxes[MAXJOYAXES]; +int32 JoystickAnalogScale[MAXJOYAXES]; +int32 JoystickAnalogDead[MAXJOYAXES]; +int32 JoystickAnalogSaturate[MAXJOYAXES]; + +// +// Screen variables +// + +int32 ScreenMode = 1; +int32 ScreenWidth = 640; +int32 ScreenHeight = 480; +int32 ScreenBPP = 8; +int32 ForceSetup = 1; + +extern char WangBangMacro[10][64]; +char RTSName[MAXRTSNAMELENGTH]; +//static char setupfilename[64]={SETUPFILENAME}; +char setupfilename[64]= {SETUPFILENAME}; +static int32 scripthandle = -1; + + + +/* +=================== += += CONFIG_FunctionNameToNum += +=================== +*/ + +int32 CONFIG_FunctionNameToNum(const char *func) +{ + int32 i; + + if (!func) return -1; + for (i=0; i= (unsigned)NUMGAMEFUNCTIONS) + { + return NULL; + } + else + { + return gamefunctions[func]; + } +} + +/* +=================== += += CONFIG_AnalogNameToNum += +=================== +*/ +int32 CONFIG_AnalogNameToNum(const char *func) +{ + if (!Bstrcasecmp(func,"analog_turning")) + { + return analog_turning; + } + if (!Bstrcasecmp(func,"analog_strafing")) + { + return analog_strafing; + } + if (!Bstrcasecmp(func,"analog_moving")) + { + return analog_moving; + } + if (!Bstrcasecmp(func,"analog_lookingupanddown")) + { + return analog_lookingupanddown; + } + return -1; +} + +const char *CONFIG_AnalogNumToName(int32 func) +{ + switch (func) + { + case analog_turning: + return "analog_turning"; + case analog_strafing: + return "analog_strafing"; + case analog_moving: + return "analog_moving"; + case analog_lookingupanddown: + return "analog_lookingupanddown"; + default: break; + } + + return NULL; +} + +/* +=================== += += CONFIG_SetDefaults += +=================== +*/ + +void CONFIG_SetDefaults(void) +{ + // JBF 20031211 + int32 i,f; + byte k1,k2; + + ScreenMode = 1; + ScreenWidth = 640; + ScreenHeight = 480; + ScreenBPP = 8; + FXDevice = 0; + MusicDevice = 0; + NumVoices = 32; + NumChannels = 2; + NumBits = 16; + MixRate = 44100; + memcpy(&gs, &gs_defaults, sizeof(gs)); + + Bstrcpy(RTSName, DEFAULTRTSFILE); + Bstrcpy(CommPlayerName, DEFAULTPLAYERNAME); + + Bstrcpy(WangBangMacro[0], MACRO1); + Bstrcpy(WangBangMacro[1], MACRO2); + Bstrcpy(WangBangMacro[2], MACRO3); + Bstrcpy(WangBangMacro[3], MACRO4); + Bstrcpy(WangBangMacro[4], MACRO5); + Bstrcpy(WangBangMacro[5], MACRO6); + Bstrcpy(WangBangMacro[6], MACRO7); + Bstrcpy(WangBangMacro[7], MACRO8); + Bstrcpy(WangBangMacro[8], MACRO9); + Bstrcpy(WangBangMacro[9], MACRO10); + + SetDefaultKeyDefinitions(0); + SetMouseDefaults(0); + + memset(MouseDigitalAxes, -1, sizeof(MouseDigitalAxes)); + for (i=0; i= (MAXMOUSEBUTTONS-2)) continue; // scroll wheel + + Bsprintf(buf,"MouseButtonClicked%d",dummy); + SCRIPT_PutString(scripthandle,"Controls", buf, CONFIG_FunctionNumToName(MouseButtonsClicked[dummy])); + } + + for (dummy=0; dummy MAX_HISTORY) curr_history = MAX_HISTORY; + + strcpy(MessageInputString, command_history[curr_history]); +} + +void CON_AddHistory(const char *commandstr) +{ + int i; + + for (i=MAX_HISTORY-1; i>=0; i--) + { + strcpy(command_history[i],command_history[i-1]); + } + strcpy(command_history[0],commandstr); + if ((++numhistory) > MAX_HISTORY) numhistory = MAX_HISTORY; +} + + +// +// Adds a command name to the command list and assigns the appropriate function pointer +// +BOOL CON_AddCommand(const char *command, void (*function)(void)) +{ + if (command != NULL && function != NULL && numcommands < MAX_CONSOLE_COMMANDS) + { +// strcpy(commandlist[numcommands].command, command); + commandlist[numcommands].command = command; + commandlist[numcommands].function = function; + + // Increment counter to set up for next command insertion + numcommands++; + + ASSERT(numcommands <= MAX_CONSOLE_COMMANDS); + + return TRUE; + } + + return FALSE; +} + +// +// Process commands +// Returns TRUE upon success +// +void CON_ProcessUserCommand(void) +{ + SHORT i=0; + char temp_message[256],command_str[256]; + + strcpy(temp_message,MessageInputString); + sscanf(Bstrlwr(temp_message),"%s", command_str); // Get the base command type + + for (i = 0; i < numcommands; i++) + { + // Don't even try if they aren't the same length + if (strlen(command_str) != strlen(commandlist[i].command)) continue; + // See if it's in there + if (CON_CommandCmp(command_str, commandlist[i].command, strlen(command_str))) + { + if (commandlist[i].function) + { + (*commandlist[i].function)(); + CON_AddHistory(MessageInputString); // Keep history only of valid input + return; + } + } + } + + if (ConPanel) + CON_ConMessage("Syntax Error or Command not enabled!"); +} + +// +// Initialize the console command list with the pre_command startup array +// +void CON_InitConsole(void) +{ + CON_COMMANDp i; + + for (i = &pre_commands[0]; i->command != NULL; i++) + { + if (!CON_AddCommand(i->command, i->function)) + { + printf("CON_InitConsole: Failed to add command contained in pre_commands list.\n"); + TerminateGame(); + exit(0); + } + } + + //printf("CON_InitConsole: Command list initialized.\n"); +} + +// +// Process as a command, anything that could be set in the options menu as well +// +void CON_ProcessOptions(void) +{ + +} + +// Clear the console screen +void CON_ClearConsole(void) +{ + short i; + + for (i=0; i 6144) + { + CON_ConMessage("ERROR: Sprite %d is out of range.",SpriteNum); + return FALSE; + } + return TRUE; +} + +// Get help on a console command +void CON_GetHelp(void) +{ + char base[80], command[80]; + short i; + + + if (sscanf(MessageInputString,"%s %s",base,command) < 2) + { + CON_ConMessage("Usage: help [keyword]"); + return; + } + + Bstrlwr(command); // Make sure operator is all lower case + + if (!strcmp(command, "xrepeat")) + { + CON_ConMessage("Usage: xrepeat [repeat value 0-255],"); + CON_ConMessage(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); + return; + } + else if (!strcmp(command, "yrepeat")) + { + CON_ConMessage("Usage: yrepeat [repeat value 0-255],"); + CON_ConMessage(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); + return; + } + else if (!strcmp(command, "translucent")) + { + CON_ConMessage("Usage: translucent [OFF/ON 0-1],"); + CON_ConMessage(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); + return; + } + else + { + CON_ConMessage("No help was located on that subject."); + } +} + +// Modify sprites xrepeat value +void CON_ModXrepeat(void) +{ + char base[80]; + SHORT op1=64,op2=-1,op3=-1; + short i; + + + if (sscanf(MessageInputString,"%s %hd %hd %hd",base,&op1,&op2,&op3) < 4) + { + strcpy(MessageInputString,"help xrepeat"); + CON_GetHelp(); + return; + } + + if (op3 == -1) + { + for (i=0; ixrepeat = op1; + else + { + if (u->ID == op2) + sp->xrepeat = op1; + } + } + if (op2 == -1) + CON_ConMessage("Xrepeat set to %d for all u->ID's for all sprites.",op1); + else + CON_ConMessage("Xrepeat set to %d for u->ID = %d for all sprites.",op1,op2); + } + else + { + // Do it only for one sprite + SPRITEp sp = &sprite[op3]; + USERp u = User[op3]; + + if (!CheckValidSprite(op3)) return; + + sp->xrepeat = op1; + CON_ConMessage("Xrepeat set to %d for sprite %d.",op1,op3); + } +} + +// Modify sprites yrepeat value +void CON_ModYrepeat(void) +{ + char base[80]; + SHORT op1=64,op2=-1,op3=-1; + short i; + + + if (sscanf(MessageInputString,"%s %hd %hd %hd",base,&op1,&op2,&op3) < 4) + { + strcpy(MessageInputString,"help yrepeat"); + CON_GetHelp(); + return; + } + + + if (op3 == -1) + { + for (i=0; iyrepeat = op1; + else + { + if (u->ID == op2) + sp->yrepeat = op1; + } + } + if (op2 == -1) + CON_ConMessage("Yrepeat set to %d for all u->ID's for all sprites.",op1); + else + CON_ConMessage("Yrepeat set to %d for u->ID = %d for all sprites.",op1,op2); + } + else + { + // Do it only for one sprite + SPRITEp sp = &sprite[op3]; + USERp u = User[op3]; + + if (!CheckValidSprite(op3)) return; + + sp->yrepeat = op1; + CON_ConMessage("Yrepeat set to %d for sprite %d.",op1,op3); + } +} + +void CON_ModTranslucent(void) +{ + char base[80]; + SHORT op1=0; + SPRITEp sp; + USERp u; + + // Format: translucent [SpriteNum] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help translucent"); + CON_GetHelp(); + return; + } + + if (!CheckValidSprite(op1)) return; + + sp = &sprite[op1]; + u = User[op1]; + + if (TEST(sp->cstat,CSTAT_SPRITE_TRANSLUCENT)) + { + RESET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT); + CON_ConMessage("Translucence RESET for sprite %d.",op1); + } + else + { + SET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT); + CON_ConMessage("Translucence SET for sprite %d.",op1); + } +} + +void CON_SoundTest(void) +{ + int handle; + int zero=0; + char base[80]; + SHORT op1=0; + + // Format: sound [number] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help sound"); + CON_GetHelp(); + return; + } + + if (op1 < 0 || op1 >= DIGI_MAX) + { + CON_ConMessage("Sound number out of range."); + return; + } + + handle = PlaySound(op1,&zero,&zero,&zero,v3df_none); +} + + +void CON_Reverb(void) +{ + char base[80]; + SHORT op1=0; + PLAYERp pp = Player + screenpeek; + + // Format: reverb [number] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help reverb"); + CON_GetHelp(); + return; + } + + CON_ConMessage("Reverb is now set to %d.",op1); + COVER_SetReverb(op1); + pp->Reverb = op1; +} + +void CON_Heap(void) +{ + /* + int totalmemory=0; + extern int TotalMemory, ActualHeap; + int i; + void *testheap; + + totalmemory = Z_AvailHeap(); + CON_ConMessage("Total heap at game startup = %d", TotalMemory); + CON_ConMessage("ActualHeap reserved for non-cache use = %d", ActualHeap); + CON_ConMessage("Total unallocated blocks in bytes minus reserved heap = %d", totalmemory); + CON_ConMessage("NOTE: Allocation exceeding ActualHeap will result in out of memory"); + // Find remaining heap space unused + i = ActualHeap; + while(i>0) + { + testheap = AllocMem(i); + if(!testheap) + i-=1024L; // Decrease in 1k increments + else + { + CON_ConMessage("Heap test result (+ or - 1k):"); + CON_ConMessage("============================="); + CON_ConMessage("Unallocated heap space remaining = %d",i); + CON_ConMessage("Unallocated heap space used = %d",ActualHeap - i); + FreeMem(testheap); + i=0; // Beam us out of here Scotty! + } + } + + if(ActualHeap < 50000L) + { + CON_ConMessage("ALERT: Memory is critically low!"); + } + */ +} + +int TileRangeMem(int start) +{ + int i; + int total=0; + + switch (start) + { + case 4096: // Evil Ninja + for (i=4096; i<=4239; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 800: // Hornet + for (i=800; i<=811; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 817: + for (i=817; i<=819; i++) // Bouncing Betty + total += tilesizx[i]*tilesizy[i]; + break; + case 820: // Skull + for (i=820; i<=854; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 960: + for (i=960; i<=1016; i++) // Serpent God + total += tilesizx[i]*tilesizy[i]; + for (i=1300; i<=1314; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 1024: + for (i=1024; i<=1175; i++) // LoWang + total += tilesizx[i]*tilesizy[i]; + break; + case 1320: + for (i=1320; i<=1396; i++) // Skeletor Priest + total += tilesizx[i]*tilesizy[i]; + break; + case 1400: + for (i=1400; i<=1440; i++) // Coolie + total += tilesizx[i]*tilesizy[i]; + for (i=4260; i<=4266; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 1441: + for (i=1441; i<=1450; i++) // Coolie Ghost + total += tilesizx[i]*tilesizy[i]; + for (i=4267; i<=4312; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 1469: + for (i=1469; i<=1497; i++) // Guardian + total += tilesizx[i]*tilesizy[i]; + for (i=1504; i<=1518; i++) + total += tilesizx[i]*tilesizy[i]; + break; + case 1580: + for (i=1580; i<=1644; i++) // Little Ripper + total += tilesizx[i]*tilesizy[i]; + break; + case 4320: + for (i=4320; i<=4427; i++) // Big Ripper + total += tilesizx[i]*tilesizy[i]; + break; + case 2540: + for (i=2540; i<=2546; i++) // Trashcan + total += tilesizx[i]*tilesizy[i]; + break; + case 4430: + for (i=4430; i<=4479; i++) // Fish + total += tilesizx[i]*tilesizy[i]; + break; + case 4490: + for (i=4490; i<=4544; i++) // Sumo + total += tilesizx[i]*tilesizy[i]; + break; + case 5023: + for (i=5023; i<=5026; i++) // Toilet Girl + total += tilesizx[i]*tilesizy[i]; + break; + case 5032: + for (i=5032; i<=5035; i++) // Wash Girl + total += tilesizx[i]*tilesizy[i]; + break; + case 2000: + for (i=2000; i<=2002; i++) // Chop Stick Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2004: + for (i=2004; i<=2009; i++) // Uzi Panel + total += tilesizx[i]*tilesizy[i]; + for (i=2040; i<=2043; i++) // Uzi Overlays + total += tilesizx[i]*tilesizy[i]; + break; + case 2010: + for (i=2010; i<=2019; i++) // Rail Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2130: + for (i=2130; i<=2137; i++) // Shuriken Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2050: + for (i=2050; i<=2053; i++) // Heart Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2054: + for (i=2054; i<=2057; i++) // HotHead Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2070: + for (i=2070; i<=2077; i++) // Rocket Launcher Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2080: + for (i=2080; i<=2083; i++) // Sword Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 4090: + for (i=4090; i<=4093; i++) // Bloody Sword Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2121: + for (i=2121; i<=2126; i++) // 40MM Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2211: + for (i=2211; i<=2216; i++) // Shotgun Panel + total += tilesizx[i]*tilesizy[i]; + for (i=2225; i<=2227; i++) // Shotgun Quad-Mode Panel + total += tilesizx[i]*tilesizy[i]; + break; + case 2220: + for (i=2220; i<=2224; i++) // Sticky Bomb Panel + total += tilesizx[i]*tilesizy[i]; + break; + } + + return total; +} + +void CON_Cache(void) +{ + char incache[8192]; // 8192 so it can index maxwalls as well + int i,j,tottiles,totsprites,totactors; + + + memset(incache,0,8192); + + // Calculate all level tiles, non-actor stuff + for (i=0; i= 0) + incache[wall[i].overpicnum] = 1; + } + + tottiles = 0; + for (i=0; i<8192; i++) + if (incache[i] > 0) + tottiles += tilesizx[i]*tilesizy[i]; + + ////////////////////////////////////////////// + + memset(incache,0,8192); + + // Sprites on the stat list get counted as cached, others don't + for (i=0; i 0) + { + switch (i) + { + case 4096: + totactors+=TileRangeMem(4096); + incache[4096]=0; + break; + case 800: + totactors+=TileRangeMem(800); + incache[800]=0; + break; + case 817: + totactors+=TileRangeMem(817); + incache[817]=0; + break; + case 820: + totactors+=TileRangeMem(820); + incache[820]=0; + break; + case 960: + totactors+=TileRangeMem(960); + incache[960]=0; + break; + //case 1024: // Lo Wang is calculated later + // totactors+=TileRangeMem(1024); + // incache[1024]=0; + //break; + case 1320: + totactors+=TileRangeMem(1320); + incache[1320]=0; + break; + case 1400: + totactors+=TileRangeMem(1400); + incache[1400]=0; + break; + case 1441: + totactors+=TileRangeMem(1441); + incache[1441]=0; + break; + case 1469: + totactors+=TileRangeMem(1469); + incache[1469]=0; + break; + case 1580: + totactors+=TileRangeMem(1580); + incache[1580]=0; + break; + case 4320: + totactors+=TileRangeMem(4320); + incache[4320]=0; + break; + case 2540: + totactors+=TileRangeMem(2540); + incache[2540]=0; + break; + case 4430: + totactors+=TileRangeMem(4430); + incache[4430]=0; + break; + case 4490: + totactors+=TileRangeMem(4490); + incache[4490]=0; + break; + case 5023: + totactors+=TileRangeMem(5023); + incache[5023]=0; + break; + case 5032: + totactors+=TileRangeMem(5032); + incache[5032]=0; + break; + case 2000: + totactors+=TileRangeMem(2000); + incache[2000]=0; + break; + case 2004: + totactors+=TileRangeMem(2004); + incache[2004]=0; + break; + case 2010: + totactors+=TileRangeMem(2010); + incache[2010]=0; + break; + case 2130: + totactors+=TileRangeMem(2130); + incache[2130]=0; + break; + case 2050: + totactors+=TileRangeMem(2050); + incache[2050]=0; + break; + case 2054: + totactors+=TileRangeMem(2054); + incache[2054]=0; + break; + case 2070: + totactors+=TileRangeMem(2070); + incache[2070]=0; + break; + case 2080: + totactors+=TileRangeMem(2080); + incache[2080]=0; + break; + case 4090: + totactors+=TileRangeMem(4090); + incache[4090]=0; + break; + case 2121: + totactors+=TileRangeMem(2121); + incache[2121]=0; + break; + case 2211: + totactors+=TileRangeMem(2211); + incache[2211]=0; + break; + case 2220: + totactors+=TileRangeMem(2220); + incache[2220]=0; + break; + + default: totsprites += tilesizx[i]*tilesizy[i]; + } + } + } + + CON_ConMessage("/////////////////////////////////////////////"); + CON_ConMessage("Current Memory Consumption:"); + CON_ConMessage("Total Tiles = %d",tottiles); + CON_ConMessage("Total Sprites = %d",totsprites); + CON_ConMessage("Total Actors = %d",totactors); + CON_ConMessage("Total Memory = %d",(tottiles+totsprites+totactors)); + CON_ConMessage("Total with LoWang = %d",(tottiles+totsprites+totactors+TileRangeMem(1024))); + CON_ConMessage("/////////////////////////////////////////////"); + +} + +void CON_SpriteInfo(void) +{ + SpriteInfo++; + if (SpriteInfo > 2) SpriteInfo = 0; + + if (SpriteInfo == 0) + CON_ConMessage("Sprite information is OFF."); + else if (SpriteInfo == 1) + CON_ConMessage("Sprite information is ON (Brief Mode)."); + else + CON_ConMessage("Sprite information is ON (Verbose Mode)."); +} + +void CON_KillSprite(void) +{ + char base[80]; + SHORT op1=0; + SPRITEp sp; + short i; + USERp u; + + // Format: kill [SpriteNum] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help kill"); + CON_GetHelp(); + return; + } + + if (op1 == -1) + { + for (i=0; iPlayerP) + SetSuicide(i); + } + CON_ConMessage("Killed all sprites except Players."); + } + else + { + if (!CheckValidSprite(op1)) return; + + SetSuicide(op1); + CON_ConMessage("Killed sprite %d.",op1); + } + +} + +void CON_SpriteDetail(void) +{ + char base[80]; + SHORT op1=0; + SPRITEp sp; + short i; + + // Format: showsprite [SpriteNum] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help showsprite"); + CON_GetHelp(); + return; + } + + if (!CheckValidSprite(op1)) return; + sp = &sprite[op1]; + + CON_ConMessage("x = %d, y = %d, z = %d",sp->x,sp->y,sp->z); + CON_ConMessage("cstat = %d, picnum = %d",sp->cstat,sp->picnum); + CON_ConMessage("shade = %d, pal = %d, clipdist = %d",sp->shade,sp->pal,sp->clipdist); + CON_ConMessage("xrepeat = %d, yrepeat = %d",sp->xrepeat, sp->yrepeat); + CON_ConMessage("xoffset = %d, yoffset = %d",sp->xoffset, sp->yoffset); + CON_ConMessage("sectnum = %d, statnum = %d",sp->sectnum, sp->statnum); + CON_ConMessage("ang = %d, owner = %d",sp->ang,sp->owner); + CON_ConMessage("xvel = %d, yvel = %d, zvel = %d",sp->xvel,sp->yvel,sp->zvel); + CON_ConMessage("lotag = %d, hitag = %d, extra = %d",sp->lotag,sp->hitag,sp->extra); +} + +void CON_UserDetail(void) +{ + char base[80]; + SHORT op1=0; + SPRITEp sp; + short i; + USERp u; + + // Format: showuser [SpriteNum] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help showsprite"); + CON_GetHelp(); + return; + } + + if (!CheckValidSprite(op1)) return; + sp = &sprite[op1]; + u = User[op1]; + + if (!u) return; + + CON_ConMessage("State = %p, Rot = %p",u->State,u->Rot); + CON_ConMessage("StateStart = %p, StateEnd = %p",u->StateStart,u->StateEnd); + CON_ConMessage("ActorActionFunc = %p",u->ActorActionFunc); + CON_ConMessage("ActorActionSet = %p",u->ActorActionSet); + CON_ConMessage("Personality = %p",u->Personality); + CON_ConMessage("Attrib = %p",u->Attrib); + CON_ConMessage("Flags = %d, Flags2 = %d, Tics = %d",u->Flags,u->Flags2,u->Tics); + CON_ConMessage("RotNum = %d, ID = %d",u->RotNum,u->ID); + CON_ConMessage("Health = %d, MaxHealth = %d",u->Health,u->MaxHealth); + CON_ConMessage("LastDamage = %d, PainThreshold = %d",u->LastDamage,u->PainThreshold); + CON_ConMessage("jump_speed = %d, jump_grav = %d",u->jump_speed,u->jump_grav); + CON_ConMessage("xchange = %d, ychange = %d, zchange = %d",u->xchange,u->ychange,u->zchange); + CON_ConMessage("ret = %d, WaitTics = %d, spal = %d",u->ret,u->WaitTics,u->spal); +} + +void CON_Quit(void) +{ + if (CommPlayers >= 2) + MultiPlayQuitFlag = TRUE; + else + QuitFlag = TRUE; +} + +void CON_MultiNameChange(void) +{ + char base[16],command[16]; + + // Format: swname [name] + if (sscanf(MessageInputString,"%6s %12s",base,command) < 2) + return; + + SendMulitNameChange(command); +} + +void CON_LoadSetup(void) +{ + /* + char base[80],command[80]; + extern char setupfilename[64]; + + // Format: showuser [SpriteNum] + if (sscanf(MessageInputString,"%s %s",base,command) < 2) + { + strcpy(MessageInputString,"help config"); + CON_GetHelp(); + return; + } + + if (!SafeFileExists(command)) + { + CON_ConMessage("CON_LoadSetup: %s does not exist.",command); + return; + } else + { + strcpy(setupfilename,command); + } + initkeys(); + CONFIG_ReadSetup(); + CONTROL_Startup( ControllerType, &GetTime, 120 ); + SetupGameButtons(); + + if (CONTROL_JoystickEnabled) + { + CONTROL_CenterJoystick(CenterCenter, UpperLeft, LowerRight, CenterThrottle, + CenterRudder); + } + CON_ConMessage("Loaded new config file."); + */ + CON_ConMessage("JonoF: Maybe later"); +} + +char *damagename[] = +{ + "WPN_STAR","WPN_UZI", + "WPN_SHOTGUN","WPN_MICRO", + "WPN_GRENADE","WPN_MINE", + "WPN_RAIL","WPN_HEART", + "WPN_HOTHEAD","WPN_NAPALM" + "WPN_RING","WPN_ROCKET", + "WPN_SWORD","WPN_FIST", + "DMG_NAPALM","DMG_MIRV_METEOR", + "DMG_SERP_METEOR","DMG_ELECTRO_SHARD", + "DMG_SECTOR_EXP","DMG_BOLT_EXP", + "DMG_TANK_SHELL_EXP","DMG_FIREBALL_EXP", + "DMG_NAPALM_EXP","DMG_SKULL_EXP", + "DMG_BASIC_EXP","DMG_GRENADE_EXP", + "DMG_MINE_EXP","DMG_MINE_SHRAP", + "DMG_MICRO_EXP","DMG_NUCLEAR_EXP", + "DMG_RADIATION_CLOUD","DMG_FLASHBOMB", + "DMG_FIREBALL_FLAMES","DMG_RIPPER_SLASH", + "DMG_SKEL_SLASH","DMG_COOLG_BASH", + "DMG_COOLG_FIRE","DMG_GORO_CHOP", + "DMG_GORO_FIREBALL","DMG_SERP_SLASH", + "DMG_LAVA_BOULDER","DMG_LAVA_SHARD", + "DMG_HORNET_STING","DMG_EEL_ELECTRO", + "DMG_SPEAR_TRAP","DMG_VOMIT", + "DMG_BLADE" +}; + +void CON_DamageData(void) +{ + + char base[80],field[80]; + SHORT op1=0; + unsigned int op2, i; + SPRITEp sp; + USERp u; + + // Format: damage [field] [item] [value] + if (sscanf(MessageInputString,"%s %s %hd %u",base,field,&op1,&op2) < 3) + { + strcpy(MessageInputString,"help damage"); + CON_GetHelp(); + return; + } + + if (op1 < -1 || op1 > 46) + { + CON_ConMessage("Damage Data index is out of range."); + return; + } + + if (!strcmp(field,"damage_lo")) + { + DamageData[op1].damage_lo = op2; + CON_ConMessage("DamageData[%s].damage_lo = %d",damagename[op1],op2); + } + else if (!strcmp(field,"damage_hi")) + { + DamageData[op1].damage_hi = op2; + CON_ConMessage("DamageData[%s].damage_hi = %d",damagename[op1],op2); + } + else if (!strcmp(field,"radius")) + { + DamageData[op1].radius = op2; + CON_ConMessage("DamageData[%s].radius = %d",damagename[op1],op2); + } + else if (!strcmp(field,"max_ammo")) + { + DamageData[op1].max_ammo = op2; + CON_ConMessage("DamageData[%s].max_ammo = %d",damagename[op1],op2); + } + else if (!strcmp(field,"min_ammo")) + { + DamageData[op1].min_ammo = op2; + CON_ConMessage("DamageData[%s].min_ammo = %d",damagename[op1],op2); + } + if (!strcmp(field,"show")) + { + if (op1 == -1) + { + for (i=op2; i<=op2+10; i+=2) + { + if (i<47) + CON_ConMessage("[%d] = %s [%d] = %s",i,damagename[i],i+1,damagename[i+1]); + } + } + else + { + CON_ConMessage(" "); + CON_ConMessage("Item = %s:",damagename[op1]); + CON_ConMessage("damage_lo = %d, damag_hi = %d",DamageData[op1].damage_lo,DamageData[op1].damage_hi); + CON_ConMessage("radius = %u",DamageData[op1].radius); + CON_ConMessage("min_ammo = %d, max_ammo = %d",DamageData[op1].min_ammo,DamageData[op1].max_ammo); + CON_ConMessage(" "); + } + } +} + +void CON_WinPachinko(void) +{ + extern BOOL Pachinko_Win_Cheat; + PLAYERp pp = Player + myconnectindex; + extern void CheckSndData(char *file, int line); + + if (CommEnabled) + return; + + Pachinko_Win_Cheat = !Pachinko_Win_Cheat; + + //CheckSndData( __FILE__, __LINE__ ); + + if (Pachinko_Win_Cheat) + PutStringInfo(pp,"Pachinko Win Cheat Enabled"); + else + PutStringInfo(pp,"Pachinko Win Cheat Disabled"); +} + +void CON_Tweak(void) +{ + char base[80], command[80]; + int op1=0; + + // Format: tweak [weapon] [number] + if (sscanf(MessageInputString,"%s %s %d",base,command,&op1) < 3) + { + strcpy(MessageInputString,"help tweak"); + CON_GetHelp(); + return; + } + + Bstrlwr(command); // Make sure operator is all lower case + if (!strcmp(command,"adjust")) + { + extern short ADJUST; + ADJUST = op1; + CON_ConMessage("Zvelocity ADJUST set to %d.",op1); + } + else if (!strcmp(command,"adjustv")) + { + extern int ADJUSTV; + ADJUSTV = op1; + CON_ConMessage("Zvelocity ADJUSTV set to %d.",op1); + } +} + +void CON_Bunny(void) +{ + PLAYERp pp = Player + myconnectindex; + + if (CommEnabled) + return; + + pp->BunnyMode = !pp->BunnyMode; + if (pp->BunnyMode) + PutStringInfo(pp,"Bunny rockets enabled!"); + else + PutStringInfo(pp,"Bunny rockets disabled!"); +} + +void CON_CheckHeap(void) +{ + /* + switch( _heapchk() ) + { + case _HEAPOK: + CON_ConMessage( "OK - heap is good\n" ); + break; + case _HEAPEMPTY: + CON_ConMessage( "OK - heap is empty\n" ); + break; + case _HEAPBADBEGIN: + CON_ConMessage( "ERROR - heap is damaged\n" ); + break; + case _HEAPBADNODE: + CON_ConMessage( "ERROR - bad node in heap\n" ); + break; + } + */ + CON_ConMessage("JonoF: Not now"); +} + +/* +void heap_dump( void ) + { + struct _heapinfo h_info; + int heap_status; + + h_info._pentry = NULL; + for(;;) { + heap_status = _heapwalk( &h_info ); + if( heap_status != _HEAPOK ) break; + printf( " %s block at %Fp of size %4.4X\n", + (h_info._useflag == _USEDENTRY ? "USED" : "FREE"), + h_info._pentry, h_info._size ); + + } + + switch( heap_status ) { + case _HEAPEND: + printf( "OK - end of heap\n" ); + break; + case _HEAPEMPTY: + printf( "OK - heap is empty\n" ); + break; + case _HEAPBADBEGIN: + printf( "ERROR - heap is damaged\n" ); + break; + case _HEAPBADPTR: + printf( "ERROR - bad pointer to heap\n" ); + break; + case _HEAPBADNODE: + + printf( "ERROR - bad node in heap\n" ); + } + } + */ + +void CON_DumpHeap(void) +{ + //heap_dump(); // Dump it. + CON_ConMessage("JonoF: Not now"); +} + +void CON_ShowMirror(void) +{ + char base[80]; + SHORT op1=0; + + // Format: showmirror [SpriteNum] + if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) + { + strcpy(MessageInputString,"help showmirror"); + CON_GetHelp(); + return; + } + + if (op1 < 0 || op1 > 9) + { + CON_ConMessage("Mirror number is out of range!"); + return; + } + + CON_ConMessage("camera is the ST1 sprite used as the view spot"); + CON_ConMessage("camspite is the SpriteNum of the drawtotile tile in editart"); + CON_ConMessage("camspic is the tile number of the drawtotile in editart"); + CON_ConMessage("iscamera is whether or not this mirror is a camera type"); + CON_ConMessage(" "); + CON_ConMessage("mirror[%d].mirrorwall = %d",op1,mirror[op1].mirrorwall); + CON_ConMessage("mirror[%d].mirrorsector = %d",op1,mirror[op1].mirrorsector); + CON_ConMessage("mirror[%d].camera = %d",op1,mirror[op1].camera); + CON_ConMessage("mirror[%d].camsprite = %d",op1,mirror[op1].camsprite); + CON_ConMessage("mirror[%d].campic = %d",op1,mirror[op1].campic); + CON_ConMessage("mirror[%d].iscamera = %d",op1,mirror[op1].ismagic); +} + +void CON_DumpSoundList(void) +{ + extern void DumpSounds(void); + + DumpSounds(); + CON_Message("Sounds dumped to dbg.foo"); + +} + diff --git a/polymer/eduke32/source/sw/src/coolg.c b/polymer/eduke32/source/sw/src/coolg.c new file mode 100644 index 000000000..6095abcf6 --- /dev/null +++ b/polymer/eduke32/source/sw/src/coolg.c @@ -0,0 +1,996 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "game.h" +#include "tags.h" +#include "ai.h" +#include "sprite.h" +#include "actor.h" +#include "weapon.h" +#include "track.h" + +ANIMATOR DoCoolgCircle,InitCoolgCircle; + +DECISION CoolgBattle[] = +{ + {50, InitCoolgCircle }, + {450, InitActorMoveCloser }, + //{456, InitActorAmbientNoise }, + //{760, InitActorRunAway }, + {1024, InitActorAttack } +}; + +DECISION CoolgOffense[] = +{ + {449, InitActorMoveCloser }, + //{554, InitActorAmbientNoise }, + {1024, InitActorAttack } +}; + +DECISION CoolgBroadcast[] = +{ + //{1, InitActorAlertNoise }, + {1, InitActorAmbientNoise }, + {1024, InitActorDecide } +}; + +DECISION CoolgSurprised[] = +{ + {100, InitCoolgCircle }, + {701, InitActorMoveCloser }, + {1024, InitActorDecide } +}; + +DECISION CoolgEvasive[] = +{ + {20, InitCoolgCircle }, + {1024, InitActorRunAway }, +}; + +DECISION CoolgLostTarget[] = +{ + {900, InitActorFindPlayer }, + {1024, InitActorWanderAround } +}; + +DECISION CoolgCloseRange[] = +{ + {800, InitActorAttack }, + {1024, InitActorReposition } +}; + +DECISION CoolgTouchTarget[] = +{ + //{50, InitCoolgCircle }, + {1024, InitActorAttack }, +}; + +PERSONALITY CoolgPersonality = +{ + CoolgBattle, + CoolgOffense, + CoolgBroadcast, + CoolgSurprised, + CoolgEvasive, + CoolgLostTarget, + CoolgCloseRange, + CoolgTouchTarget +}; + +ATTRIBUTE CoolgAttrib = +{ + {60, 80, 150, 190}, // Speeds + {3, 0, -2, -3}, // Tic Adjusts + 3, // MaxWeapons; + { + DIGI_CGAMBIENT, DIGI_CGALERT, 0, + DIGI_CGPAIN, DIGI_CGSCREAM, DIGI_CGMATERIALIZE, + DIGI_CGTHIGHBONE,DIGI_CGMAGIC,DIGI_CGMAGICHIT,0 + } +}; + +////////////////////// +// +// COOLG RUN +////////////////////// + +#define COOLG_RUN_RATE 40 + +ANIMATOR DoCoolgMove,NullAnimator,DoStayOnFloor, DoActorDebris, NullCoolg, DoCoolgBirth; + +STATE s_CoolgRun[5][4] = +{ + { + {COOLG_RUN_R0 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[0][1]}, + {COOLG_RUN_R0 + 1, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[0][2]}, + {COOLG_RUN_R0 + 2, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[0][3]}, + {COOLG_RUN_R0 + 3, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[0][0]}, + }, + { + {COOLG_RUN_R1 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[1][1]}, + {COOLG_RUN_R1 + 1, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[1][2]}, + {COOLG_RUN_R1 + 2, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[1][3]}, + {COOLG_RUN_R1 + 3, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[1][0]}, + }, + { + {COOLG_RUN_R2 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[2][1]}, + {COOLG_RUN_R2 + 1, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[2][2]}, + {COOLG_RUN_R2 + 2, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[2][3]}, + {COOLG_RUN_R2 + 3, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[2][0]}, + }, + { + {COOLG_RUN_R3 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[3][1]}, + {COOLG_RUN_R3 + 1, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[3][2]}, + {COOLG_RUN_R3 + 2, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[3][3]}, + {COOLG_RUN_R3 + 3, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[3][0]}, + }, + { + {COOLG_RUN_R4 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[4][1]}, + {COOLG_RUN_R4 + 1, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[4][2]}, + {COOLG_RUN_R4 + 2, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[4][3]}, + {COOLG_RUN_R4 + 3, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgRun[4][0]}, + } +}; + +STATEp sg_CoolgRun[] = +{ + &s_CoolgRun[0][0], + &s_CoolgRun[1][0], + &s_CoolgRun[2][0], + &s_CoolgRun[3][0], + &s_CoolgRun[4][0] +}; + +////////////////////// +// +// COOLG STAND +// +////////////////////// + + +STATE s_CoolgStand[5][1] = +{ + { + {COOLG_RUN_R0 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgStand[0][0]}, + }, + { + {COOLG_RUN_R1 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgStand[1][0]}, + }, + { + {COOLG_RUN_R2 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgStand[2][0]}, + }, + { + {COOLG_RUN_R3 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgStand[3][0]}, + }, + { + {COOLG_RUN_R4 + 0, COOLG_RUN_RATE, DoCoolgMove, &s_CoolgStand[4][0]}, + } +}; + +STATEp sg_CoolgStand[] = +{ + &s_CoolgStand[0][0], + &s_CoolgStand[1][0], + &s_CoolgStand[2][0], + &s_CoolgStand[3][0], + &s_CoolgStand[4][0] +}; + +////////////////////// +// +// COOLG CLUB +// +////////////////////// + +#define COOLG_RATE 16 +ANIMATOR InitCoolgBash; + +STATE s_CoolgClub[5][6] = +{ + { + {COOLG_CLUB_R0 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[0][1]}, + {COOLG_RUN_R0 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[0][2]}, + {COOLG_CLUB_R0 + 1, 0|SF_QUICK_CALL, InitCoolgBash, &s_CoolgClub[0][3]}, + {COOLG_CLUB_R0 + 1, COOLG_RATE, NullCoolg, &s_CoolgClub[0][4]}, + {COOLG_CLUB_R0 + 1, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgClub[0][5]}, + {COOLG_CLUB_R0 + 1, COOLG_RATE, DoCoolgMove, &s_CoolgClub[0][5]} + }, + { + {COOLG_CLUB_R1 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[1][1]}, + {COOLG_RUN_R1 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[1][2]}, + {COOLG_CLUB_R1 + 1, 0|SF_QUICK_CALL, InitCoolgBash, &s_CoolgClub[1][3]}, + {COOLG_CLUB_R1 + 1, COOLG_RATE, NullCoolg, &s_CoolgClub[1][4]}, + {COOLG_CLUB_R1 + 1, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgClub[1][5]}, + {COOLG_CLUB_R1 + 1, COOLG_RATE, DoCoolgMove, &s_CoolgClub[1][5]} + }, + { + {COOLG_CLUB_R2 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[2][1]}, + {COOLG_RUN_R2 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[2][2]}, + {COOLG_CLUB_R2 + 1, 0|SF_QUICK_CALL, InitCoolgBash, &s_CoolgClub[2][3]}, + {COOLG_CLUB_R2 + 1, COOLG_RATE, NullCoolg, &s_CoolgClub[2][4]}, + {COOLG_CLUB_R2 + 1, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgClub[2][5]}, + {COOLG_CLUB_R2 + 1, COOLG_RATE, DoCoolgMove, &s_CoolgClub[2][5]} + }, + { + {COOLG_CLUB_R3 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[3][1]}, + {COOLG_RUN_R3 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[3][2]}, + {COOLG_CLUB_R3 + 1, 0|SF_QUICK_CALL, InitCoolgBash, &s_CoolgClub[3][3]}, + {COOLG_CLUB_R3 + 1, COOLG_RATE, NullCoolg, &s_CoolgClub[3][4]}, + {COOLG_CLUB_R3 + 1, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgClub[3][5]}, + {COOLG_CLUB_R3 + 1, COOLG_RATE, DoCoolgMove, &s_CoolgClub[3][5]} + }, + { + {COOLG_CLUB_R4 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[4][1]}, + {COOLG_RUN_R4 + 0, COOLG_RATE, NullCoolg, &s_CoolgClub[4][2]}, + {COOLG_CLUB_R4 + 1, 0|SF_QUICK_CALL, InitCoolgBash, &s_CoolgClub[4][3]}, + {COOLG_CLUB_R4 + 1, COOLG_RATE, NullCoolg, &s_CoolgClub[4][4]}, + {COOLG_CLUB_R4 + 1, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgClub[4][5]}, + {COOLG_CLUB_R4 + 1, COOLG_RATE, DoCoolgMove, &s_CoolgClub[4][5]} + } +}; + +STATEp sg_CoolgClub[] = +{ + &s_CoolgClub[0][0], + &s_CoolgClub[1][0], + &s_CoolgClub[2][0], + &s_CoolgClub[3][0], + &s_CoolgClub[4][0] +}; + +////////////////////// +// +// COOLG FIRE +// +////////////////////// + +ANIMATOR InitCoolgFire; +#define COOLG_FIRE_RATE 12 + +STATE s_CoolgAttack[5][7] = +{ + { + {COOLG_FIRE_R0 + 0, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[0][1]}, + {COOLG_FIRE_R0 + 1, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[0][2]}, + {COOLG_FIRE_R0 + 2, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[0][3]}, + {COOLG_FIRE_R0 + 2, 0|SF_QUICK_CALL, InitCoolgFire, &s_CoolgAttack[0][4]}, + {COOLG_FIRE_R0 + 2, COOLG_FIRE_RATE, NullCoolg, &s_CoolgAttack[0][5]}, + {COOLG_FIRE_R0 + 2, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgAttack[0][6]}, + {COOLG_RUN_R0 + 2, COOLG_FIRE_RATE, DoCoolgMove, &s_CoolgAttack[0][6]} + }, + { + {COOLG_FIRE_R1 + 0, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[1][1]}, + {COOLG_FIRE_R1 + 1, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[1][2]}, + {COOLG_FIRE_R1 + 2, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[1][3]}, + {COOLG_FIRE_R1 + 2, 0|SF_QUICK_CALL, InitCoolgFire, &s_CoolgAttack[1][4]}, + {COOLG_FIRE_R1 + 2, COOLG_FIRE_RATE, NullCoolg, &s_CoolgAttack[1][5]}, + {COOLG_FIRE_R1 + 2, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgAttack[1][6]}, + {COOLG_RUN_R0 + 2, COOLG_FIRE_RATE, DoCoolgMove, &s_CoolgAttack[1][6]} + }, + { + {COOLG_FIRE_R2 + 0, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[2][1]}, + {COOLG_FIRE_R2 + 1, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[2][2]}, + {COOLG_FIRE_R2 + 2, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[2][3]}, + {COOLG_FIRE_R2 + 2, 0|SF_QUICK_CALL, InitCoolgFire, &s_CoolgAttack[2][4]}, + {COOLG_FIRE_R2 + 2, COOLG_FIRE_RATE, NullCoolg, &s_CoolgAttack[2][5]}, + {COOLG_FIRE_R2 + 2, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgAttack[2][6]}, + {COOLG_RUN_R0 + 2, COOLG_FIRE_RATE, DoCoolgMove, &s_CoolgAttack[2][6]} + }, + { + {COOLG_RUN_R3 + 0, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[3][1]}, + {COOLG_RUN_R3 + 1, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[3][2]}, + {COOLG_RUN_R3 + 2, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[3][3]}, + {COOLG_RUN_R3 + 2, 0|SF_QUICK_CALL, InitCoolgFire, &s_CoolgAttack[3][4]}, + {COOLG_RUN_R3 + 2, COOLG_FIRE_RATE, NullCoolg, &s_CoolgAttack[3][5]}, + {COOLG_RUN_R3 + 2, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgAttack[3][6]}, + {COOLG_RUN_R0 + 2, COOLG_FIRE_RATE, DoCoolgMove, &s_CoolgAttack[3][6]} + }, + { + {COOLG_RUN_R4 + 0, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[4][1]}, + {COOLG_RUN_R4 + 1, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[4][2]}, + {COOLG_RUN_R4 + 2, COOLG_FIRE_RATE*2, NullCoolg, &s_CoolgAttack[4][3]}, + {COOLG_RUN_R4 + 2, 0|SF_QUICK_CALL, InitCoolgFire, &s_CoolgAttack[4][4]}, + {COOLG_RUN_R4 + 2, COOLG_FIRE_RATE, NullCoolg, &s_CoolgAttack[4][5]}, + {COOLG_RUN_R4 + 2, 0|SF_QUICK_CALL, InitActorDecide, &s_CoolgAttack[4][6]}, + {COOLG_RUN_R0 + 2, COOLG_FIRE_RATE, DoCoolgMove, &s_CoolgAttack[4][6]} + } +}; + +STATEp sg_CoolgAttack[] = +{ + &s_CoolgAttack[0][0], + &s_CoolgAttack[1][0], + &s_CoolgAttack[2][0], + &s_CoolgAttack[3][0], + &s_CoolgAttack[4][0] +}; + +////////////////////// +// +// COOLG PAIN +// +////////////////////// + +#define COOLG_PAIN_RATE 15 +ANIMATOR DoCoolgPain; + +STATE s_CoolgPain[5][2] = +{ + { + {COOLG_PAIN_R0 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[0][1]}, + {COOLG_PAIN_R0 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[0][1]}, + }, + { + {COOLG_RUN_R1 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[1][1]}, + {COOLG_RUN_R1 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[1][1]}, + }, + { + {COOLG_RUN_R2 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[2][1]}, + {COOLG_RUN_R2 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[2][1]}, + }, + { + {COOLG_RUN_R3 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[3][1]}, + {COOLG_RUN_R3 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[3][1]}, + }, + { + {COOLG_RUN_R4 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[4][1]}, + {COOLG_RUN_R4 + 0, COOLG_PAIN_RATE, DoCoolgPain, &s_CoolgPain[4][1]}, + }, +}; + +STATEp sg_CoolgPain[] = +{ + s_CoolgPain[0], + s_CoolgPain[1], + s_CoolgPain[2], + s_CoolgPain[3], + s_CoolgPain[4] +}; + + +////////////////////// +// +// COOLG DIE +// +////////////////////// + +#define COOLG_DIE_RATE 20 + +#define COOLG_DIE 4307 +#define COOLG_DEAD 4307+5 +ANIMATOR DoCoolgDeath; +STATE s_CoolgDie[] = +{ + {COOLG_DIE + 0, COOLG_DIE_RATE, DoCoolgDeath, &s_CoolgDie[1]}, + {COOLG_DIE + 1, COOLG_DIE_RATE, DoCoolgDeath, &s_CoolgDie[2]}, + {COOLG_DIE + 2, COOLG_DIE_RATE, DoCoolgDeath, &s_CoolgDie[3]}, + {COOLG_DIE + 3, COOLG_DIE_RATE, DoCoolgDeath, &s_CoolgDie[4]}, + {COOLG_DIE + 4, COOLG_DIE_RATE, DoCoolgDeath, &s_CoolgDie[5]}, + {COOLG_DIE + 5, COOLG_DIE_RATE, DoCoolgDeath, &s_CoolgDie[5]}, +}; + +STATEp sg_CoolgDie[] = +{ + s_CoolgDie +}; + +STATE s_CoolgDead[] = +{ + {COOLG_DEAD, SF_QUICK_CALL, QueueFloorBlood, &s_CoolgDead[1]}, + {COOLG_DEAD, COOLG_DIE_RATE, DoActorDebris, &s_CoolgDead[1]}, +}; + +STATEp sg_CoolgDead[] = +{ + s_CoolgDead +}; + +////////////////////// +// +// COOLG BIRTH +// +////////////////////// + +#define COOLG_BIRTH_RATE 20 +#define COOLG_BIRTH 4268 + +STATE s_CoolgBirth[] = +{ + {COOLG_BIRTH + 0, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[1]}, + {COOLG_BIRTH + 1, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[2]}, + {COOLG_BIRTH + 2, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[3]}, + {COOLG_BIRTH + 3, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[4]}, + {COOLG_BIRTH + 4, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[5]}, + {COOLG_BIRTH + 5, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[6]}, + {COOLG_BIRTH + 6, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[7]}, + {COOLG_BIRTH + 7, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[8]}, + {COOLG_BIRTH + 8, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[9]}, + {COOLG_BIRTH + 8, COOLG_BIRTH_RATE, NullAnimator, &s_CoolgBirth[10]}, + {COOLG_BIRTH + 8, 0|SF_QUICK_CALL, DoCoolgBirth, &s_CoolgBirth[10]} +}; + +STATEp sg_CoolgBirth[] = +{ + s_CoolgBirth +}; + +/* +STATEp *Stand[MAX_WEAPONS]; +STATEp *Run; +STATEp *Jump; +STATEp *Fall; +STATEp *Crawl; +STATEp *Swim; +STATEp *Fly; +STATEp *Rise; +STATEp *Sit; +STATEp *Look; +STATEp *Climb; +STATEp *Pain; +STATEp *Death1; +STATEp *Death2; +STATEp *Dead; +STATEp *DeathJump; +STATEp *DeathFall; +STATEp *CloseAttack[2]; +STATEp *Attack[6]; +STATEp *Special[2]; +*/ + + +ACTOR_ACTION_SET CoolgActionSet = +{ + sg_CoolgStand, + sg_CoolgRun, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, //climb + sg_CoolgPain, //pain + sg_CoolgDie, + NULL, + sg_CoolgDead, + NULL, + NULL, +// {sg_CoolgClub}, + {sg_CoolgAttack}, + {1024}, + {sg_CoolgAttack}, + {1024}, + {NULL,NULL}, + NULL, + NULL +}; + +int DoCoolgMatchPlayerZ(short SpriteNum); + +void +CoolgCommon(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + sp->clipdist = (200) >> 2; + //u->floor_dist = Z(5); + u->floor_dist = Z(16); + u->ceiling_dist = Z(20); + + u->sz = sp->z; + + sp->xrepeat = 42; + sp->yrepeat = 42; + SET(sp->extra, SPRX_PLAYER_OR_ENEMY); +} + +int +SetupCoolg(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u; + ANIMATOR DoActorDecide; + + if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + { + u = User[SpriteNum]; + ASSERT(u); + } + else + { + User[SpriteNum] = u = SpawnUser(SpriteNum,COOLG_RUN_R0,s_CoolgRun[0]); + u->Health = HEALTH_COOLIE_GHOST; + } + + ChangeState(SpriteNum, s_CoolgRun[0]); + u->Attrib = &CoolgAttrib; + DoActorSetSpeed(SpriteNum, NORM_SPEED); + u->StateEnd = s_CoolgDie; + u->Rot = sg_CoolgRun; + + EnemyDefaults(SpriteNum, &CoolgActionSet, &CoolgPersonality); + + SET(u->Flags, SPR_NO_SCAREDZ|SPR_XFLIP_TOGGLE); + + CoolgCommon(SpriteNum); + + return 0; +} + +extern short TotalKillable; + +int +NewCoolg(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + USERp nu; + SPRITEp np; + ANIMATOR DoActorDecide; + short new; + + new = SpawnSprite(STAT_ENEMY, COOLG_RUN_R0, &s_CoolgBirth[0], sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 50); + + nu = User[new]; + np = &sprite[new]; + + ChangeState(new, &s_CoolgBirth[0]); + nu->StateEnd = s_CoolgDie; + nu->Rot = sg_CoolgRun; + np->pal = nu->spal = u->spal; + + nu->ActorActionSet = &CoolgActionSet; + + np->shade = sp->shade; + nu->Personality = &CoolgPersonality; + nu->Attrib = &CoolgAttrib; + + // special case + TotalKillable++; + CoolgCommon(new); + + return 0; +} + + +int +DoCoolgBirth(short new) +{ + SPRITEp sp; + USERp u; + ANIMATOR DoActorDecide; + + u = User[new]; + sp = &sprite[new]; + + u->Health = HEALTH_COOLIE_GHOST; + u->Attrib = &CoolgAttrib; + DoActorSetSpeed(new, NORM_SPEED); + + ChangeState(new, s_CoolgRun[0]); + u->StateEnd = s_CoolgDie; + u->Rot = sg_CoolgRun; + + EnemyDefaults(new, &CoolgActionSet, &CoolgPersonality); + // special case + TotalKillable--; + + SET(u->Flags, SPR_NO_SCAREDZ|SPR_XFLIP_TOGGLE); + CoolgCommon(new); + + return 0; +} + +int NullCoolg(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + u->ShellNum -= ACTORMOVETICS; + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + DoCoolgMatchPlayerZ(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + return 0; +} + + +int DoCoolgMatchPlayerZ(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + SPRITEp tsp = User[SpriteNum]->tgt_sp; + int zdiff,zdist; + int loz,hiz; + + int bound; + + // If blocking bits get unset, just die + if (!TEST(sp->cstat,CSTAT_SPRITE_BLOCK) || !TEST(sp->cstat,CSTAT_SPRITE_BLOCK_HITSCAN)) + { + InitBloodSpray(SpriteNum, TRUE, 105); + InitBloodSpray(SpriteNum, TRUE, 105); + UpdateSinglePlayKills(SpriteNum); + SetSuicide(SpriteNum); + } + + // actor does a sine wave about u->sz - this is the z mid point + + zdiff = (SPRITEp_MID(tsp)) - u->sz; + + // check z diff of the player and the sprite + zdist = Z(20 + RANDOM_RANGE(100)); // put a random amount + //zdist = Z(20); + if (labs(zdiff) > zdist) + { + if (zdiff > 0) + u->sz += 170 * ACTORMOVETICS; + else + u->sz -= 170 * ACTORMOVETICS; + } + +#define COOLG_BOB_AMT (Z(8)) + + // save off lo and hi z + loz = u->loz; + hiz = u->hiz; + + // adjust loz/hiz for water depth + if (u->lo_sectp && SectUser[u->lo_sectp - sector] && SectUser[u->lo_sectp - sector]->depth) + loz -= Z(SectUser[u->lo_sectp - sector]->depth) - Z(8); + + // lower bound + if (u->lo_sp) + bound = loz - u->floor_dist; + else + bound = loz - u->floor_dist - COOLG_BOB_AMT; + + if (u->sz > bound) + { + u->sz = bound; + } + + // upper bound + if (u->hi_sp) + bound = hiz + u->ceiling_dist; + else + bound = hiz + u->ceiling_dist + COOLG_BOB_AMT; + + if (u->sz < bound) + { + u->sz = bound; + } + + u->sz = min(u->sz, loz - u->floor_dist); + u->sz = max(u->sz, hiz + u->ceiling_dist); + + u->Counter = (u->Counter + (ACTORMOVETICS<<3)) & 2047; + sp->z = u->sz + ((COOLG_BOB_AMT * (int)sintable[u->Counter]) >> 14); + + bound = u->hiz + u->ceiling_dist + COOLG_BOB_AMT; + if (sp->z < bound) + { + // bumped something + sp->z = u->sz = bound + COOLG_BOB_AMT; + } + + return 0; +} + +int InitCoolgCircle(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + + u->ActorActionFunc = DoCoolgCircle; + + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + // set it close + DoActorSetSpeed(SpriteNum, FAST_SPEED); + + // set to really fast + sp->xvel = 400; + // angle adjuster + u->Counter2 = sp->xvel/3; + // random angle direction + if (RANDOM_P2(1024) < 512) + u->Counter2 = -u->Counter2; + + // z velocity + u->jump_speed = 400 + RANDOM_P2(256); + if (labs(u->sz - u->hiz) < labs(u->sz - u->loz)) + u->jump_speed = -u->jump_speed; + + u->WaitTics = (RANDOM_RANGE(3)+1) * 120; + + (*u->ActorActionFunc)(SpriteNum); + + return 0; +} + +int DoCoolgCircle(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + SPRITEp tsp = User[SpriteNum]->tgt_sp; + int nx,ny,bound; + + + sp->ang = NORM_ANGLE(sp->ang + u->Counter2); + + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + if (!move_actor(SpriteNum, nx, ny, 0L)) + { + InitActorReposition(SpriteNum); + return 0; + } + + // move in the z direction + u->sz -= u->jump_speed * ACTORMOVETICS; + + bound = u->hiz + u->ceiling_dist + COOLG_BOB_AMT; + if (u->sz < bound) + { + // bumped something + u->sz = bound; + InitActorReposition(SpriteNum); + return 0; + } + + // time out + if ((u->WaitTics -= ACTORMOVETICS) < 0) + { + InitActorReposition(SpriteNum); + u->WaitTics = 0; + return 0; + } + + return 0; +} + + +int +DoCoolgDeath(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + int nx, ny; + + + RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); + RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); + sp->xrepeat = 42; + sp->shade = -10; + + if (TEST(u->Flags, SPR_FALLING)) + { + DoFall(SpriteNum); + } + else + { + DoFindGroundPoint(SpriteNum); + u->floor_dist = 0; + DoBeginFall(SpriteNum); + } + + if (TEST(u->Flags, SPR_SLIDING)) + DoActorSlide(SpriteNum); + + // slide while falling + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + u->ret = move_sprite(SpriteNum, nx, ny, 0L, u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, ACTORMOVETICS); + DoFindGroundPoint(SpriteNum); + + // on the ground + if (sp->z >= u->loz) + { + RESET(u->Flags, SPR_FALLING|SPR_SLIDING); + RESET(sp->cstat, CSTAT_SPRITE_YFLIP); // If upside down, reset it + NewStateGroup(SpriteNum, u->ActorActionSet->Dead); + return 0; + } + + return 0; +} + +int DoCoolgMove(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + if ((u->ShellNum -= ACTORMOVETICS) <= 0) + { + switch (u->FlagOwner) + { + case 0: + SET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); + u->ShellNum = SEC(2); + break; + case 1: + PlaySound(DIGI_VOID3, &sp->x, &sp->y, &sp->z, v3df_follow); + RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); + SET(sp->cstat, CSTAT_SPRITE_INVISIBLE); + u->ShellNum = SEC(1) + SEC(RANDOM_RANGE(2)); + break; + case 2: + SET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); + RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); + u->ShellNum = SEC(2); + break; + case 3: + PlaySound(DIGI_VOID3, &sp->x, &sp->y, &sp->z, v3df_follow); + RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); + RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); + u->ShellNum = SEC(2) + SEC(RANDOM_RANGE(3)); + break; + default: + u->FlagOwner = 0; + break; + } + u->FlagOwner++; + if (u->FlagOwner > 3) u->FlagOwner = 0; + } + + if (u->FlagOwner-1 == 0) + { + sp->xrepeat--; + sp->shade++; + if (sp->xrepeat < 4) sp->xrepeat = 4; + if (sp->shade > 126) + { + sp->shade = 127; + sp->hitag = 9998; + } + } + else if (u->FlagOwner-1 == 2) + { + sp->hitag = 0; + sp->xrepeat++; + sp->shade--; + if (sp->xrepeat > 42) sp->xrepeat = 42; + if (sp->shade < -10) sp->shade = -10; + } + else if (u->FlagOwner == 0) + { + sp->xrepeat = 42; + sp->shade = -10; + sp->hitag = 0; + } + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + if (u->track >= 0) + ActorFollowTrack(SpriteNum, ACTORMOVETICS); + else + { + (*u->ActorActionFunc)(SpriteNum); + } + + if (RANDOM_P2(1024) < 32 && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) + InitCoolgDrip(SpriteNum); + + DoCoolgMatchPlayerZ(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + + return 0; + +} + +int DoCoolgPain(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + NullCoolg(SpriteNum); + + if ((u->WaitTics -= ACTORMOVETICS) <= 0) + InitActorDecide(SpriteNum); + + return 0; +} + + +#include "saveable.h" + +static saveable_code saveable_coolg_code[] = +{ + SAVE_CODE(CoolgCommon), + SAVE_CODE(SetupCoolg), + SAVE_CODE(NewCoolg), + SAVE_CODE(DoCoolgBirth), + SAVE_CODE(NullCoolg), + SAVE_CODE(DoCoolgMatchPlayerZ), + SAVE_CODE(InitCoolgCircle), + SAVE_CODE(DoCoolgCircle), + SAVE_CODE(DoCoolgDeath), + SAVE_CODE(DoCoolgMove), + SAVE_CODE(DoCoolgPain), +}; + +static saveable_data saveable_coolg_data[] = +{ + SAVE_DATA(CoolgBattle), + SAVE_DATA(CoolgOffense), + SAVE_DATA(CoolgBroadcast), + SAVE_DATA(CoolgSurprised), + SAVE_DATA(CoolgEvasive), + SAVE_DATA(CoolgLostTarget), + SAVE_DATA(CoolgCloseRange), + SAVE_DATA(CoolgTouchTarget), + + SAVE_DATA(CoolgPersonality), + + SAVE_DATA(CoolgAttrib), + + SAVE_DATA(s_CoolgRun), + SAVE_DATA(sg_CoolgRun), + SAVE_DATA(s_CoolgStand), + SAVE_DATA(sg_CoolgStand), + SAVE_DATA(s_CoolgClub), + SAVE_DATA(sg_CoolgClub), + SAVE_DATA(s_CoolgAttack), + SAVE_DATA(sg_CoolgAttack), + SAVE_DATA(s_CoolgPain), + SAVE_DATA(sg_CoolgPain), + SAVE_DATA(s_CoolgDie), + SAVE_DATA(sg_CoolgDie), + SAVE_DATA(s_CoolgDead), + SAVE_DATA(sg_CoolgDead), + SAVE_DATA(s_CoolgBirth), + SAVE_DATA(sg_CoolgBirth), + + SAVE_DATA(CoolgActionSet), +}; + +saveable_module saveable_coolg = +{ + // code + saveable_coolg_code, + SIZ(saveable_coolg_code), + + // data + saveable_coolg_data, + SIZ(saveable_coolg_data) +}; diff --git a/polymer/eduke32/source/sw/src/coolie.c b/polymer/eduke32/source/sw/src/coolie.c new file mode 100644 index 000000000..0f830fc9d --- /dev/null +++ b/polymer/eduke32/source/sw/src/coolie.c @@ -0,0 +1,736 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "tags.h" +#include "ai.h" +#include "sprite.h" +#include "actor.h" +#include "track.h" +#include "weapon.h" + +ANIMATOR InitCoolieCharge; + +DECISION CoolieBattle[] = +{ + {700, InitCoolieCharge }, + {990, InitActorMoveCloser }, + {1000, InitActorAttackNoise }, + {1024, InitActorRunAway } +}; + +DECISION CoolieOffense[] = +{ + {700, InitCoolieCharge }, + {1015, InitActorMoveCloser }, + {1024, InitActorAttackNoise } +}; + +DECISION CoolieBroadcast[] = +{ + //{1, InitActorAlertNoise }, + {16, InitActorAmbientNoise }, + {1024, InitActorDecide } +}; + +DECISION CoolieSurprised[] = +{ + {700, InitActorMoveCloser }, + {703, InitActorAmbientNoise }, + {1024, InitActorDecide } +}; + +DECISION CoolieEvasive[] = +{ + {10, InitActorEvade }, + {1024, NULL } +}; + +DECISION CoolieLostTarget[] = +{ + {900, InitActorFindPlayer }, + {1024, InitActorWanderAround } +}; + +DECISION CoolieCloseRange[] = +{ + {400, InitCoolieCharge }, + {1024, InitActorReposition } +}; + +PERSONALITY CooliePersonality = +{ + CoolieBattle, + CoolieOffense, + CoolieBroadcast, + CoolieSurprised, + CoolieEvasive, + CoolieLostTarget, + CoolieCloseRange, + CoolieCloseRange +}; + +ATTRIBUTE CoolieAttrib = +{ + {60, 80, 100, 200}, // Speeds + {3, 0, -2, -3}, // Tic Adjusts + 3, // MaxWeapons; + { + DIGI_COOLIEAMBIENT, DIGI_COOLIEALERT, DIGI_COOLIEALERT, + DIGI_COOLIEPAIN, 0, DIGI_CGMATERIALIZE, + DIGI_COOLIEEXPLODE,0,0,0 + } +}; + + +////////////////////// +// +// COOLIE RUN +// +////////////////////// + +#define COOLIE_RATE 12 + +ANIMATOR DoCoolieMove,NullCoolie,DoStayOnFloor, + DoActorDebris, SpawnCoolieExp, + SpawnCoolg; + +STATE s_CoolieRun[5][4] = +{ + { + {COOLIE_RUN_R0 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[0][1]}, + {COOLIE_RUN_R0 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[0][2]}, + {COOLIE_RUN_R0 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[0][3]}, + {COOLIE_RUN_R0 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[0][0]} + }, + { + {COOLIE_RUN_R1 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[1][1]}, + {COOLIE_RUN_R1 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[1][2]}, + {COOLIE_RUN_R1 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[1][3]}, + {COOLIE_RUN_R1 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[1][0]} + }, + { + {COOLIE_RUN_R2 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[2][1]}, + {COOLIE_RUN_R2 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[2][2]}, + {COOLIE_RUN_R2 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[2][3]}, + {COOLIE_RUN_R2 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[2][0]} + }, + { + {COOLIE_RUN_R3 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[3][1]}, + {COOLIE_RUN_R3 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[3][2]}, + {COOLIE_RUN_R3 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[3][3]}, + {COOLIE_RUN_R3 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[3][0]} + }, + { + {COOLIE_RUN_R4 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[4][1]}, + {COOLIE_RUN_R4 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[4][2]}, + {COOLIE_RUN_R4 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[4][3]}, + {COOLIE_RUN_R4 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieRun[4][0]}, + } +}; + +STATEp sg_CoolieRun[] = +{ + &s_CoolieRun[0][0], + &s_CoolieRun[1][0], + &s_CoolieRun[2][0], + &s_CoolieRun[3][0], + &s_CoolieRun[4][0] +}; + +////////////////////// +// +// COOLIE CHARGE +// +////////////////////// + +#define COOLIE_RATE 12 + +ANIMATOR DoCoolieMove,NullCoolie,DoStayOnFloor, + DoActorDebris, SpawnCoolieExp, + SpawnCoolg; + +STATE s_CoolieCharge[5][4] = +{ + { + {COOLIE_CHARGE_R0 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[0][1]}, + {COOLIE_CHARGE_R0 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[0][2]}, + {COOLIE_CHARGE_R0 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[0][3]}, + {COOLIE_CHARGE_R0 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[0][0]} + }, + { + {COOLIE_CHARGE_R1 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[1][1]}, + {COOLIE_CHARGE_R1 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[1][2]}, + {COOLIE_CHARGE_R1 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[1][3]}, + {COOLIE_CHARGE_R1 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[1][0]} + }, + { + {COOLIE_CHARGE_R2 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[2][1]}, + {COOLIE_CHARGE_R2 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[2][2]}, + {COOLIE_CHARGE_R2 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[2][3]}, + {COOLIE_CHARGE_R2 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[2][0]} + }, + { + {COOLIE_CHARGE_R3 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[3][1]}, + {COOLIE_CHARGE_R3 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[3][2]}, + {COOLIE_CHARGE_R3 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[3][3]}, + {COOLIE_CHARGE_R3 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[3][0]} + }, + { + {COOLIE_CHARGE_R4 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[4][1]}, + {COOLIE_CHARGE_R4 + 1, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[4][2]}, + {COOLIE_CHARGE_R4 + 2, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[4][3]}, + {COOLIE_CHARGE_R4 + 3, COOLIE_RATE, DoCoolieMove, &s_CoolieCharge[4][0]}, + } +}; + +STATEp sg_CoolieCharge[] = +{ + &s_CoolieCharge[0][0], + &s_CoolieCharge[1][0], + &s_CoolieCharge[2][0], + &s_CoolieCharge[3][0], + &s_CoolieCharge[4][0] +}; + +////////////////////// +// +// COOLIE STAND +// +////////////////////// + +STATE s_CoolieStand[5][6] = +{ + { + {COOLIE_RUN_R0 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieStand[0][0]} + }, + { + {COOLIE_RUN_R1 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieStand[1][0]} + }, + { + {COOLIE_RUN_R2 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieStand[2][0]} + }, + { + {COOLIE_RUN_R3 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieStand[3][0]} + }, + { + {COOLIE_RUN_R4 + 0, COOLIE_RATE, DoCoolieMove, &s_CoolieStand[4][0]} + } +}; + +STATEp sg_CoolieStand[] = +{ + &s_CoolieStand[0][0], + &s_CoolieStand[1][0], + &s_CoolieStand[2][0], + &s_CoolieStand[3][0], + &s_CoolieStand[4][0] +}; + +////////////////////// +// +// COOLIE PAIN +// +////////////////////// + +#define COOLIE_PAIN_RATE 60 +ANIMATOR CooliePain; + +STATE s_CooliePain[5][1] = +{ + { + {COOLIE_PAIN_R0 + 0, COOLIE_PAIN_RATE, CooliePain, &s_CooliePain[0][0]}, + //{COOLIE_PAIN_R0 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_CooliePain[0][0]} + }, + { + {COOLIE_PAIN_R1 + 0, COOLIE_PAIN_RATE, CooliePain, &s_CooliePain[1][0]}, + //{COOLIE_PAIN_R1 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_CooliePain[1][0]} + }, + { + {COOLIE_PAIN_R2 + 0, COOLIE_PAIN_RATE, CooliePain, &s_CooliePain[2][0]}, + //{COOLIE_PAIN_R2 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_CooliePain[2][0]} + }, + { + {COOLIE_PAIN_R3 + 0, COOLIE_PAIN_RATE, CooliePain, &s_CooliePain[3][0]}, + //{COOLIE_PAIN_R3 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_CooliePain[3][0]} + }, + { + {COOLIE_PAIN_R4 + 0, COOLIE_PAIN_RATE, CooliePain, &s_CooliePain[4][0]}, + //{COOLIE_PAIN_R4 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_CooliePain[4][0]} + } +}; + +STATEp sg_CooliePain[] = +{ + &s_CooliePain[0][0], + &s_CooliePain[1][0], + &s_CooliePain[2][0], + &s_CooliePain[3][0], + &s_CooliePain[4][0] +}; + +////////////////////// +// +// COOLIE DIE +// +////////////////////// + +#define COOLIE_DIE_RATE 30 +ANIMATOR DoCoolieWaitBirth; + +STATE s_CoolieDie[] = +{ + {COOLIE_DIE + 0, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[1]}, + + {COOLIE_DIE + 0, 0|SF_QUICK_CALL, SpawnCoolieExp, &s_CoolieDie[2]}, + + {COOLIE_DIE + 1, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[3]}, + {COOLIE_DIE + 2, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[4]}, + {COOLIE_DIE + 3, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[5]}, + {COOLIE_DIE + 4, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[6]}, + {COOLIE_DIE + 5, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[7]}, + {COOLIE_DIE + 6, COOLIE_DIE_RATE, NullCoolie, &s_CoolieDie[8]}, + {COOLIE_DIE + 7, COOLIE_DIE_RATE, DoCoolieWaitBirth, &s_CoolieDie[8]}, + + {COOLIE_DIE + 7, COOLIE_DIE_RATE*5, DoActorDebris, &s_CoolieDie[10]}, + {COOLIE_DIE + 7, 0|SF_QUICK_CALL, SpawnCoolg, &s_CoolieDie[11]}, + {COOLIE_DEAD_NOHEAD, SF_QUICK_CALL, QueueFloorBlood, &s_CoolieDie[12]}, + {COOLIE_DEAD_NOHEAD, COOLIE_DIE_RATE, DoActorDebris, &s_CoolieDie[12]} +}; + +STATEp sg_CoolieDie[] = +{ + s_CoolieDie +}; + +STATE s_CoolieDead[] = +{ + {COOLIE_DEAD, COOLIE_DIE_RATE, DoActorDebris, &s_CoolieDead[0]}, +}; + +STATEp sg_CoolieDead[] = +{ + s_CoolieDead +}; + +/* +typedef struct +{ +#define MAX_ACTOR_CLOSE_ATTACK 2 +#define MAX_ACTOR_ATTACK 6 +STATEp *Stand; +STATEp *Run; +STATEp *Jump; +STATEp *Fall; +STATEp *Crawl; +STATEp *Swim; +STATEp *Fly; +STATEp *Rise; +STATEp *Sit; +STATEp *Look; +STATEp *Climb; +STATEp *Pain; +STATEp *Death1; +STATEp *Death2; +STATEp *Dead; +STATEp *DeathJump; +STATEp *DeathFall; + +STATEp *CloseAttack[MAX_ACTOR_CLOSE_ATTACK]; +short CloseAttackPercent[MAX_ACTOR_CLOSE_ATTACK]; + +STATEp *Attack[MAX_ACTOR_ATTACK]; +short AttackPercent[MAX_ACTOR_ATTACK]; + +STATEp *Special[2]; +STATEp *Duck; +STATEp *Dive; +}ACTOR_ACTION_SET,*ACTOR_ACTION_SETp; +*/ + +ACTOR_ACTION_SET CoolieActionSet = +{ + sg_CoolieStand, + sg_CoolieRun, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, //climb + sg_CooliePain, //pain + sg_CoolieDie, + NULL, + sg_CoolieDead, + NULL, + NULL, + {sg_CoolieCharge}, + {1024}, + {sg_CoolieCharge}, + {1024}, + {NULL}, + NULL, + NULL +}; + +VOID EnemyDefaults(short SpriteNum, ACTOR_ACTION_SETp action, PERSONALITYp person) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = &sprite[SpriteNum]; + unsigned int wpn; + short wpn_cnt; + short depth = 0; + extern short TotalKillable; + extern BOOL DebugSecret; + + switch (u->ID) + { + case PACHINKO1: + case PACHINKO2: + case PACHINKO3: + case PACHINKO4: + case 623: + case TOILETGIRL_R0: + case WASHGIRL_R0: + case CARGIRL_R0: + case MECHANICGIRL_R0: + case SAILORGIRL_R0: + case PRUNEGIRL_R0: + case TRASHCAN: + case BUNNY_RUN_R0: + break; + default: + { + TotalKillable++; +#if DEBUG + if (DebugSecret) + { + sprintf(ds,"COUNTED: spnum %d, pic %d, x %d, y %d",SpriteNum,sp->picnum,sp->x,sp->y); + DebugWriteString(ds); + } +#endif + } + + break; + } + + RESET(sp->cstat, CSTAT_SPRITE_RESTORE); + + u->spal = sp->pal; + + u->RotNum = 5; + sp->clipdist = (256) >> 2; + + u->zclip = Z(48); + u->lo_step = Z(32); + + u->floor_dist = u->zclip - u->lo_step; + u->ceiling_dist = SPRITEp_SIZE_Z(sp) - u->zclip; + + u->Radius = 400; + + u->MaxHealth = u->Health; + + u->PainThreshold = DIV16(u->Health) - 1; + //u->PainThreshold = DIV4(u->Health) - 1; + + SET(sp->cstat,CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + SET(sp->extra,SPRX_PLAYER_OR_ENEMY); + + sprite[SpriteNum].picnum = u->State->Pic; + change_sprite_stat(SpriteNum, STAT_ENEMY); + + u->Personality = person; + u->ActorActionSet = action; + + DoActorZrange(SpriteNum); + + //KeepActorOnFloor(SpriteNum); // for swimming actors + + // make sure we start in the water if thats where we are + if (u->lo_sectp) // && SectUser[u->lo_sectp - sector]) + { + short i,nexti; + short sectnum = u->lo_sectp - sector; + + if (SectUser[sectnum] && TEST(u->lo_sectp->extra, SECTFX_SINK)) + { + depth = SectUser[sectnum]->depth; + } + else + { + TRAVERSE_SPRITE_SECT(headspritesect[sectnum],i,nexti) + { + SPRITEp np = &sprite[i]; + if (np->picnum == ST1 && np->hitag == SECT_SINK) + { + depth = np->lotag; + } + } + } + } + + if (depth && labs(sp->z - u->loz) < Z(8)) + { + sp->z += Z(depth); + u->loz = sp->z; + u->oz = sp->z; + } + + if (!action) + return; + + NewStateGroup(SpriteNum, u->ActorActionSet->Run); + + u->ActorActionFunc = DoActorDecide; + + // find the number of long range attacks + for (wpn = wpn_cnt = 0; wpn < SIZ(u->ActorActionSet->Attack); wpn++) + { + if (u->ActorActionSet->Attack[wpn]) + wpn_cnt++; + else + break; + } + + // for actors this tells the number of weapons available + // for player it tells the current weapon + u->WeaponNum = wpn_cnt; +} + +int +SetupCoolie(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u; + ANIMATOR DoActorDecide; + + if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + { + u = User[SpriteNum]; + ASSERT(u); + } + else + { + User[SpriteNum] = u = SpawnUser(SpriteNum,COOLIE_RUN_R0,s_CoolieRun[0]); + u->Health = HEALTH_COOLIE; + } + + ChangeState(SpriteNum,s_CoolieRun[0]); + u->Attrib = &CoolieAttrib; + DoActorSetSpeed(SpriteNum, NORM_SPEED); + u->StateEnd = s_CoolieDie; + u->Rot = sg_CoolieRun; + + EnemyDefaults(SpriteNum, &CoolieActionSet, &CooliePersonality); + + sp->xrepeat = 42; + sp->yrepeat = 42; + + SET(u->Flags, SPR_XFLIP_TOGGLE); + + return 0; +} + + +int SpawnCoolg(short SpriteNum) +{ + int NewCoolg(short); + USERp u = User[SpriteNum]; + + // Don't do a ghost every time + if (RANDOM_RANGE(1000) > 700) return 0; + + NewCoolg(SpriteNum); + + PlaySpriteSound(SpriteNum,attr_extra1,v3df_follow); + + return 0; +} + +int CooliePain(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + if (!TEST(u->Flags,SPR_CLIMBING)) + KeepActorOnFloor(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + if ((u->WaitTics -= ACTORMOVETICS) <= 0) + InitActorDecide(SpriteNum); + + return 0; +} + +int NullCoolie(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + if (!TEST(u->Flags,SPR_CLIMBING)) + KeepActorOnFloor(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + return 0; +} + +int DoCoolieMove(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + if (u->track >= 0) + ActorFollowTrack(SpriteNum, ACTORMOVETICS); + else + (*u->ActorActionFunc)(SpriteNum); + + KeepActorOnFloor(SpriteNum); + + if (DoActorSectorDamage(SpriteNum)) + { + return 0; + } + + if (Distance(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y) < 1200) + { + //DoActorDie(SpriteNum, -3); + UpdateSinglePlayKills(SpriteNum); + DoActorDie(SpriteNum, SpriteNum); + return 0; + } + + return 0; +} + +int InitCoolieCharge(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + if (RANDOM_P2(1024) > 950) + PlaySound(DIGI_COOLIESCREAM, &sp->x, &sp->y, &sp->z, v3df_follow); + + DoActorSetSpeed(SpriteNum, FAST_SPEED); + + InitActorMoveCloser(SpriteNum); + + NewStateGroup(SpriteNum, sg_CoolieCharge); + + return 0; +} + + +int +DoCoolieWaitBirth(short SpriteNum) +{ + SPRITEp sp; + USERp u; + + u = User[SpriteNum]; + sp = &sprite[SpriteNum]; + + if ((u->Counter -= ACTORMOVETICS) <= 0) + { + ChangeState(SpriteNum,&s_CoolieDie[9]); + } + + return 0; +} + + +#include "saveable.h" + +static saveable_code saveable_coolie_code[] = +{ + SAVE_CODE(EnemyDefaults), + SAVE_CODE(SetupCoolie), + SAVE_CODE(SpawnCoolg), + SAVE_CODE(CooliePain), + SAVE_CODE(NullCoolie), + SAVE_CODE(DoCoolieMove), + SAVE_CODE(InitCoolieCharge), + SAVE_CODE(DoCoolieWaitBirth), +}; + +static saveable_data saveable_coolie_data[] = +{ + SAVE_DATA(CoolieBattle), + SAVE_DATA(CoolieOffense), + SAVE_DATA(CoolieBroadcast), + SAVE_DATA(CoolieSurprised), + SAVE_DATA(CoolieEvasive), + SAVE_DATA(CoolieLostTarget), + SAVE_DATA(CoolieCloseRange), + + SAVE_DATA(CooliePersonality), + + SAVE_DATA(CoolieAttrib), + + SAVE_DATA(s_CoolieRun), + SAVE_DATA(sg_CoolieRun), + SAVE_DATA(s_CoolieCharge), + SAVE_DATA(sg_CoolieCharge), + SAVE_DATA(s_CoolieStand), + SAVE_DATA(sg_CoolieStand), + SAVE_DATA(s_CooliePain), + SAVE_DATA(sg_CooliePain), + SAVE_DATA(s_CoolieDie), + SAVE_DATA(sg_CoolieDie), + SAVE_DATA(s_CoolieDead), + SAVE_DATA(sg_CoolieDead), + + SAVE_DATA(CoolieActionSet), +}; + +saveable_module saveable_coolie = +{ + // code + saveable_coolie_code, + SIZ(saveable_coolie_code), + + // data + saveable_coolie_data, + SIZ(saveable_coolie_data) +}; diff --git a/polymer/eduke32/source/sw/src/copysect.c b/polymer/eduke32/source/sw/src/copysect.c new file mode 100644 index 000000000..8963f8451 --- /dev/null +++ b/polymer/eduke32/source/sw/src/copysect.c @@ -0,0 +1,238 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "names2.h" +#include "game.h" +#include "tags.h" +#include "weapon.h" +#include "sprite.h" +#include "track.h" + +void CopySectorWalls(short dest_sectnum, short src_sectnum) +{ + short dest_wall_num, src_wall_num, start_wall; + + dest_wall_num = sector[dest_sectnum].wallptr; + src_wall_num = sector[src_sectnum].wallptr; + + start_wall = dest_wall_num; + + do + { + wall[dest_wall_num].picnum = wall[src_wall_num].picnum; + + wall[dest_wall_num].xrepeat = wall[src_wall_num].xrepeat; + wall[dest_wall_num].yrepeat = wall[src_wall_num].yrepeat; + wall[dest_wall_num].overpicnum = wall[src_wall_num].overpicnum; + wall[dest_wall_num].pal = wall[src_wall_num].pal; + wall[dest_wall_num].cstat = wall[src_wall_num].cstat; + wall[dest_wall_num].shade = wall[src_wall_num].shade; + wall[dest_wall_num].xpanning = wall[src_wall_num].xpanning; + wall[dest_wall_num].ypanning = wall[src_wall_num].ypanning; + wall[dest_wall_num].hitag = wall[src_wall_num].hitag; + wall[dest_wall_num].lotag = wall[src_wall_num].lotag; + wall[dest_wall_num].extra = wall[src_wall_num].extra; + + if (wall[dest_wall_num].nextwall >= 0 && wall[src_wall_num].nextwall >= 0) + { + wall[wall[dest_wall_num].nextwall].picnum = wall[wall[src_wall_num].nextwall].picnum; + wall[wall[dest_wall_num].nextwall].xrepeat = wall[wall[src_wall_num].nextwall].xrepeat; + wall[wall[dest_wall_num].nextwall].yrepeat = wall[wall[src_wall_num].nextwall].yrepeat; + wall[wall[dest_wall_num].nextwall].overpicnum = wall[wall[src_wall_num].nextwall].overpicnum; + wall[wall[dest_wall_num].nextwall].pal = wall[wall[src_wall_num].nextwall].pal; + wall[wall[dest_wall_num].nextwall].cstat = wall[wall[src_wall_num].nextwall].cstat; + wall[wall[dest_wall_num].nextwall].shade = wall[wall[src_wall_num].nextwall].shade; + wall[wall[dest_wall_num].nextwall].xpanning = wall[wall[src_wall_num].nextwall].xpanning; + wall[wall[dest_wall_num].nextwall].ypanning = wall[wall[src_wall_num].nextwall].ypanning; + wall[wall[dest_wall_num].nextwall].hitag = wall[wall[src_wall_num].nextwall].hitag; + wall[wall[dest_wall_num].nextwall].lotag = wall[wall[src_wall_num].nextwall].lotag; + wall[wall[dest_wall_num].nextwall].extra = wall[wall[src_wall_num].nextwall].extra; + } + + dest_wall_num = wall[dest_wall_num].point2; + src_wall_num = wall[src_wall_num].point2; + } + while (dest_wall_num != start_wall); +} + +void CopySectorMatch(short match) +{ + short ed,nexted,ss,nextss; + SPRITEp dest_sp, src_sp; + SECTORp dsectp,ssectp; + short kill, nextkill; + SPRITEp k; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_DEST], ed, nexted) + { + dest_sp = &sprite[ed]; + dsectp = §or[dest_sp->sectnum]; + + if (match != sprite[ed].lotag) + continue; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_SOURCE], ss, nextss) + { + src_sp = &sprite[ss]; + + if (SP_TAG2(src_sp) == SPRITE_TAG2(ed) && + SP_TAG3(src_sp) == SPRITE_TAG3(ed)) + { + short src_move, nextsrc_move; + ssectp = §or[src_sp->sectnum]; + + // !!!!!AAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHH + // Don't kill anything you don't have to + // this wall killing things on a Queue causing + // invalid situations + +#if 1 + // kill all sprites in the dest sector that need to be + TRAVERSE_SPRITE_SECT(headspritesect[dest_sp->sectnum], kill, nextkill) + { + k = &sprite[kill]; + + // kill anything not invisible + if (!TEST(k->cstat, CSTAT_SPRITE_INVISIBLE)) + { + if (User[kill]) + { + // be safe with the killing + //SetSuicide(kill); + } + else + { + SpriteQueueDelete(kill); // new function to allow killing - hopefully + KillSprite(kill); + } + } + } +#endif + + CopySectorWalls(dest_sp->sectnum, src_sp->sectnum); + + TRAVERSE_SPRITE_SECT(headspritesect[src_sp->sectnum], src_move, nextsrc_move) + { + // don't move ST1 Copy Tags + if (SPRITE_TAG1(src_move) != SECT_COPY_SOURCE) + { + int sx,sy,dx,dy,src_xoff,src_yoff,trash; + + // move sprites from source to dest - use center offset + + // get center of src and dest sect + SectorMidPoint(src_sp->sectnum, &sx, &sy, &trash); + SectorMidPoint(dest_sp->sectnum, &dx, &dy, &trash); + + // get offset + src_xoff = sx - sprite[src_move].x; + src_yoff = sy - sprite[src_move].y; + + // move sprite to dest sector + sprite[src_move].x = dx - src_xoff; + sprite[src_move].y = dy - src_yoff; + + // change sector + changespritesect(src_move, dest_sp->sectnum); + + // check to see if it moved on to a sector object + if (TEST(sector[dest_sp->sectnum].extra, SECTFX_SECTOR_OBJECT)) + { + SECTOR_OBJECTp sop; + extern short GlobSpeedSO; + + // find and add sprite to SO + sop = DetectSectorObject(§or[sprite[src_move].sectnum]); + AddSpriteToSectorObject(src_move, sop); + + // update sprites postions so they aren't in the + // wrong place for one frame + GlobSpeedSO = 0; + RefreshPoints(sop, 0, 0, TRUE); + } + } + } + + // copy sector user if there is one + if (SectUser[src_sp->sectnum] || SectUser[dest_sp->sectnum]) + { + SECT_USERp ssectu = GetSectUser(src_sp->sectnum); + SECT_USERp dsectu = GetSectUser(dest_sp->sectnum); + + memcpy(dsectu, ssectu, sizeof(SECT_USER)); + } + + dsectp->hitag = ssectp->hitag; + dsectp->lotag = ssectp->lotag; + + dsectp->floorz = ssectp->floorz; + dsectp->ceilingz = ssectp->ceilingz; + + dsectp->floorshade = ssectp->floorshade; + dsectp->ceilingshade = ssectp->ceilingshade; + + dsectp->floorpicnum = ssectp->floorpicnum; + dsectp->ceilingpicnum = ssectp->ceilingpicnum; + + dsectp->floorheinum = ssectp->floorheinum; + dsectp->ceilingheinum = ssectp->ceilingheinum; + + dsectp->floorpal = ssectp->floorpal; + dsectp->ceilingpal = ssectp->ceilingpal; + + dsectp->floorxpanning = ssectp->floorxpanning; + dsectp->ceilingxpanning = ssectp->ceilingxpanning; + + dsectp->floorypanning = ssectp->floorypanning; + dsectp->ceilingypanning = ssectp->ceilingypanning; + + dsectp->floorstat = ssectp->floorstat; + dsectp->ceilingstat = ssectp->ceilingstat; + + dsectp->extra = ssectp->extra; + dsectp->visibility = ssectp->visibility; + } + } + } + + // do this outside of processing loop for safety + + // kill all matching dest + TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_DEST], ed, nexted) + { + if (match == sprite[ed].lotag) + KillSprite(ed); + } + + // kill all matching sources + TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_SOURCE], ss, nextss) + { + if (match == sprite[ss].lotag) + KillSprite(ss); + } + +} diff --git a/polymer/eduke32/source/sw/src/damage.h b/polymer/eduke32/source/sw/src/damage.h new file mode 100644 index 000000000..c395632f8 --- /dev/null +++ b/polymer/eduke32/source/sw/src/damage.h @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifdef DAMAGE_TABLE +#define DAMAGE_ENTRY(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon) \ + { init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, NULL, NULL, -1, -1 }, +#define DAMAGE_ENTRY_WPN(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_name, ammo_name, weapon_pickup, ammo_pickup ) \ + { init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_name, ammo_name, weapon_pickup, ammo_pickup }, +#endif + +#ifdef DAMAGE_ENUM +#define DAMAGE_ENTRY(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon) \ + id, +#define DAMAGE_ENTRY_WPN(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_name, ammo_name, weapon_pickup, ammo_pickup ) \ + id, +#endif + +// DAMAGES //////////////////////////////////////////////////////////////////// + +// weapon +DAMAGE_ENTRY(WPN_FIST, InitWeaponFist, 10, 40, 0, -1, -1, -1) +DAMAGE_ENTRY_WPN(WPN_STAR, InitWeaponStar, 5, 10, 0, 99, 3, -1, "Shurikens", NULL, 9, -1) +DAMAGE_ENTRY_WPN(WPN_SHOTGUN, InitWeaponShotgun, 4, 4, 0, 52, 1, -1, "Riot Gun", "Shotshells", 8, 24) +DAMAGE_ENTRY_WPN(WPN_UZI, InitWeaponUzi, 5, 7, 0, 200, 1, -1, "UZI Submachine Gun", "UZI Clip", 50, 50) +DAMAGE_ENTRY_WPN(WPN_MICRO, InitWeaponMicro, 15, 30, 0, 50, 1, -1, "Missile Launcher", "Missiles", 5, 5) +DAMAGE_ENTRY_WPN(WPN_GRENADE, InitWeaponGrenade, 15, 30, 0, 50, 1, -1, "Grenade Launcher", "Grenade Shells", 6, 8) +DAMAGE_ENTRY_WPN(WPN_MINE, InitWeaponMine, 5, 10, 0, 20, 1, -1, "Sticky Bombs", NULL, 5, -1) +DAMAGE_ENTRY_WPN(WPN_RAIL, InitWeaponRail, 40, 60, 0, 20, 1, -1, "Rail Gun", "Rail Gun Rods", 10, 10) +DAMAGE_ENTRY_WPN(WPN_HOTHEAD, InitWeaponHothead, 10, 25, 0, 80, 1, -1, "Guardian Head", "Firebursts", 30, 60) +DAMAGE_ENTRY_WPN(WPN_HEART, InitWeaponHeart, 75, 100, 0, 5, 1, -1, "Ripper Heart", "Deathcoils", 1, 6) + +DAMAGE_ENTRY(WPN_NAPALM, InitWeaponHothead, 50, 100, 0, 100, 40, WPN_HOTHEAD) +DAMAGE_ENTRY(WPN_RING, InitWeaponHothead, 15, 50, 0, 100, 20, WPN_HOTHEAD) +DAMAGE_ENTRY(WPN_ROCKET, InitWeaponMicro, 30, 60, 0, 100, 1, WPN_MICRO) +DAMAGE_ENTRY(WPN_SWORD, InitWeaponSword, 50, 80, 0, -1, -1, -1) + +// extra weapons connected to other + +// spell +DAMAGE_ENTRY(DMG_NAPALM, NULL, 90, 150, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_MIRV_METEOR, NULL, 35, 65, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_SERP_METEOR, NULL, 7, 15, 0, -1, -1, -1) + +// radius damage +DAMAGE_ENTRY(DMG_ELECTRO_SHARD, NULL, 2, 6, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_SECTOR_EXP, NULL, 50, 100, 3200, -1, -1, -1) +DAMAGE_ENTRY(DMG_BOLT_EXP, NULL, 80, 160, 3200, -1, -1, -1) +DAMAGE_ENTRY(DMG_TANK_SHELL_EXP, NULL, 80, 200, 4500, -1, -1, -1) +DAMAGE_ENTRY(DMG_FIREBALL_EXP, NULL, -1, -1, 1000, -1, -1, -1) +DAMAGE_ENTRY(DMG_NAPALM_EXP, NULL, 60, 90, 3200, -1, -1, -1) +DAMAGE_ENTRY(DMG_SKULL_EXP, NULL, 40, 75, 4500, -1, -1, -1) +DAMAGE_ENTRY(DMG_BASIC_EXP, NULL, 10, 25, 1000, -1, -1, -1) +DAMAGE_ENTRY(DMG_GRENADE_EXP, NULL, 70, 140, 6500, -1, -1, -1) +DAMAGE_ENTRY(DMG_MINE_EXP, NULL, 85, 115, 6500, -1, -1, -1) +DAMAGE_ENTRY(DMG_MINE_SHRAP, NULL, 15, 30, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_MICRO_EXP, NULL, 50, 100, 4500, -1, -1, -1) +DAMAGE_ENTRY_WPN(DMG_NUCLEAR_EXP, NULL, 0, 800, 30000, -1, -1, -1, "Nuclear Warhead", "Heat Seeker Card", 1, 5) +DAMAGE_ENTRY(DMG_RADIATION_CLOUD, NULL, 2, 6, 5000, -1, -1, -1) +DAMAGE_ENTRY(DMG_FLASHBOMB, NULL, 100, 150, 16384, -1, -1, -1) + +DAMAGE_ENTRY(DMG_FIREBALL_FLAMES, NULL, 2, 6, 300, -1, -1, -1) + +// actor +DAMAGE_ENTRY(DMG_RIPPER_SLASH, NULL, 10, 30, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_SKEL_SLASH, NULL, 10, 20, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_COOLG_BASH, NULL, 10, 20, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_COOLG_FIRE, NULL, 15, 30, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_GORO_CHOP, NULL, 20, 40, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_GORO_FIREBALL, NULL, 5, 20, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_SERP_SLASH, NULL, 75, 75, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_LAVA_BOULDER, NULL, 100, 100, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_LAVA_SHARD, NULL, 25, 25, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_HORNET_STING, NULL, 5, 10, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_EEL_ELECTRO, NULL, 10, 40, 3400, -1, -1, -1) + +// misc +DAMAGE_ENTRY(DMG_SPEAR_TRAP, NULL, 15, 20, 0, -1, -1, -1) +DAMAGE_ENTRY(DMG_VOMIT, NULL, 5, 15, 0, -1, -1, -1) + +// inanimate objects +DAMAGE_ENTRY(DMG_BLADE, NULL, 10, 20, 0, -1, -1, -1) +DAMAGE_ENTRY(MAX_WEAPONS, NULL, 10, 20, 0, -1, -1, -1) + +#undef DAMAGE_ENTRY +#undef DAMAGE_ENTRY_WPN diff --git a/polymer/eduke32/source/sw/src/demo.c b/polymer/eduke32/source/sw/src/demo.c new file mode 100644 index 000000000..1cda6dee9 --- /dev/null +++ b/polymer/eduke32/source/sw/src/demo.c @@ -0,0 +1,656 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +//#define MAIN +//#define QUIET +#include "build.h" +#include "cache1d.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "net.h" + +#include "mytypes.h" +#include "control.h" +#include "function.h" +#include "demo.h" + +#include "player.h" +#include "menus.h" + + +DFILE DemoFileIn = DF_ERR; +FILE *DemoFileOut; +BOOL DemoPlaying = FALSE; +BOOL DemoRecording = FALSE; +BOOL DemoEdit = FALSE; +BOOL DemoMode = FALSE; +BOOL DemoModeMenuState = FALSE; +BOOL DemoOverride = FALSE; +char DemoFileName[16] = "demo.dmo"; +char DemoLevelName[16] = ""; +extern BOOL NewGame; + +// Demo sync stuff +FILE *DemoSyncFile; +BOOL DemoSyncTest = FALSE, DemoSyncRecord = FALSE; +char DemoTmpName[16] = ""; + +SW_PACKET DemoBuffer[DEMO_BUFFER_MAX]; +int DemoRecCnt = 0; // Can only record 1-player game + +BOOL DemoDone; + +VOID DemoWriteHeader(VOID); +VOID DemoReadHeader(VOID); +VOID DemoReadBuffer(VOID); + + +// +// DemoDebug Vars +// + +// DemoDebugMode will close the file after every write +BOOL DemoDebugMode = FALSE; +//BOOL DemoDebugMode = TRUE; +BOOL DemoInitOnce = FALSE; +short DemoDebugBufferMax = 1; + +extern char LevelName[]; +extern char LevelSong[16]; +extern BYTE FakeMultiNumPlayers; +extern BOOL QuitFlag; + +/////////////////////////////////////////// +// +// Demo File Manipulation +// +/////////////////////////////////////////// + +char *DemoSyncFileName(VOID) +{ + static char file_name[32]; + char *ptr; + + strcpy(file_name, DemoFileName); + + if ((ptr = strchr(file_name, '.')) == 0) + strcat(file_name, ".dms"); + else + { + *ptr = '\0'; + strcat(file_name, ".dms"); + } + + return file_name; +} + +VOID +DemoSetup(VOID) +{ + if (DemoRecording) + { + if (DemoSyncRecord) + DemoSyncFile = fopen(DemoSyncFileName(),"wb"); + + DemoWriteHeader(); + memset(&DemoBuffer, -1, sizeof(DemoBuffer)); + } + + if (DemoPlaying) + { + if (DemoSyncRecord) + DemoSyncFile = fopen(DemoSyncFileName(),"wb"); + if (DemoSyncTest) + DemoSyncFile = fopen(DemoSyncFileName(),"rb"); + + DemoReadHeader(); + memset(&DemoBuffer, -1, sizeof(DemoBuffer)); + DemoReadBuffer(); + } +} + +VOID +DemoRecordSetup(VOID) +{ + if (DemoRecording) + { + if (DemoSyncRecord) + DemoSyncFile = fopen(DemoSyncFileName(),"wb"); + + DemoWriteHeader(); + memset(&DemoBuffer, -1, sizeof(DemoBuffer)); + } +} + +VOID +DemoPlaySetup(VOID) +{ + if (DemoPlaying) + { + if (DemoSyncRecord) + DemoSyncFile = fopen(DemoSyncFileName(),"wb"); + if (DemoSyncTest) + DemoSyncFile = fopen(DemoSyncFileName(),"rb"); + + DemoReadHeader(); + memset(&DemoBuffer, -1, sizeof(DemoBuffer)); + DemoReadBuffer(); + } +} + +VOID +DemoWriteHeader(VOID) +{ + DEMO_HEADER dh; + DEMO_START_POS dsp; + PLAYERp pp; + + DemoFileOut = fopen(DemoFileName, "wb"); + + if (!DemoFileOut) + return; + + strcpy(dh.map_name, LevelName); + strcpy(dh.LevelSong, LevelSong); + dh.Level = Level; + + if (FakeMultiNumPlayers) + dh.numplayers = FakeMultiNumPlayers; + else + dh.numplayers = numplayers; + + fwrite(&dh, sizeof(dh), 1, DemoFileOut); + + for (pp = Player; pp < Player + dh.numplayers; pp++) + { + dsp.x = pp->posx; + dsp.y = pp->posy; + dsp.z = pp->posz; + fwrite(&dsp, sizeof(dsp), 1, DemoFileOut); + fwrite(&pp->Flags, sizeof(pp->Flags), 1, DemoFileOut); + fwrite(&pp->pang, sizeof(pp->pang), 1, DemoFileOut); + } + + fwrite(&Skill, sizeof(Skill), 1, DemoFileOut); + fwrite(&gNet, sizeof(gNet), 1, DemoFileOut); + + if (DemoDebugMode) + { + DemoDebugBufferMax = numplayers; + fclose(DemoFileOut); + } +} + +VOID +DemoReadHeader(VOID) +{ + DEMO_HEADER dh; + DEMO_START_POS dsp; + PLAYERp pp; + +#if DEMO_FILE_TYPE != DEMO_FILE_GROUP + if (DemoEdit) + { + DemoFileIn = fopen(DemoFileName, "rb+"); + } + else +#endif + { + //DemoFileIn = fopen(DemoFileName, "rb"); + DemoFileIn = DOPEN_READ(DemoFileName); + } + + if (DemoFileIn == DF_ERR) + { + TerminateGame(); + printf("File %s is not a valid demo file.",DemoFileName); + exit(0); + } + + DREAD(&dh, sizeof(dh), 1, DemoFileIn); + + strcpy(DemoLevelName, dh.map_name); + strcpy(LevelSong, dh.LevelSong); + Level = dh.Level; + if (dh.numplayers > 1) + { + FakeMultiNumPlayers = dh.numplayers; + } + else + numplayers = dh.numplayers; + + for (pp = Player; pp < Player + dh.numplayers; pp++) + { + DREAD(&dsp, sizeof(dsp), 1, DemoFileIn); + pp->posx = dsp.x; + pp->posy = dsp.y; + pp->posz = dsp.z; + COVERupdatesector(pp->posx, pp->posy, &pp->cursectnum); + //pp->cursectnum = 0; + //updatesectorz(pp->posx, pp->posy, pp->posz, &pp->cursectnum); + DREAD(&pp->Flags, sizeof(pp->Flags), 1, DemoFileIn); + DREAD(&pp->pang, sizeof(pp->pang), 1, DemoFileIn); + } + + DREAD(&Skill, sizeof(Skill), 1, DemoFileIn); + DREAD(&gNet, sizeof(gNet), 1, DemoFileIn); +} + +VOID +DemoDebugWrite(VOID) +{ + int size; + + DemoFileOut = fopen(DemoFileName, "ab"); + + ASSERT(DemoFileOut); + + size = sizeof(SW_PACKET) * DemoDebugBufferMax; + fwrite(&DemoBuffer, size, 1, DemoFileOut); + memset(&DemoBuffer, -1, size); + + fclose(DemoFileOut); +} + +VOID +DemoWriteBuffer(VOID) +{ + fwrite(&DemoBuffer, sizeof(DemoBuffer), 1, DemoFileOut); + memset(&DemoBuffer, -1, sizeof(DemoBuffer)); +} + +VOID +DemoReadBuffer(VOID) +{ + memset(&DemoBuffer, -1, sizeof(DemoBuffer)); + DREAD(&DemoBuffer, sizeof(DemoBuffer), 1, DemoFileIn); +} + +VOID +DemoBackupBuffer(VOID) +{ +#if DEMO_FILE_TYPE != DEMO_FILE_GROUP + FILE *NewDemoFile; + FILE *OldDemoFile = DemoFileIn; + int pos,i; + char copy_buffer; + char NewDemoFileName[16] = "!"; + + // seek backwards to beginning of last buffer + fseek(OldDemoFile, -sizeof(DemoBuffer), SEEK_CUR); + pos = ftell(OldDemoFile); + + // open a new edit file + strcat(NewDemoFileName, DemoFileName); + NewDemoFile = fopen(NewDemoFileName, "wb"); + + rewind(OldDemoFile); + + // copy old demo to new demo + for (i = 0; i < pos; i++) + { + fread(©_buffer, sizeof(copy_buffer), 1, OldDemoFile); + fwrite(©_buffer,sizeof(copy_buffer), 1, NewDemoFile); + } + + DemoFileOut = NewDemoFile; + fclose(OldDemoFile); +#endif +} + +VOID +DemoTerm(VOID) +{ + if (DemoRecording) + { + // if already closed + if (DemoFileOut == NULL) + return; + + if (DemoDebugMode) + { + DemoFileOut = fopen(DemoFileName, "ab"); + ASSERT(DemoFileOut); + } + else + { + // paste on a -1 record to the current buffer + if (DemoRecCnt < DEMO_BUFFER_MAX) + memset(&DemoBuffer[DemoRecCnt], -1, sizeof(DemoBuffer[DemoRecCnt])); + + DemoWriteBuffer(); + } + + // write at least 1 record at the end filled with -1 + // just for good measure + memset(&DemoBuffer[0], -1, sizeof(DemoBuffer[0])); + fwrite(&DemoBuffer[0], sizeof(DemoBuffer[0]), 1, DemoFileOut); + + fclose(DemoFileOut); + DemoFileOut = NULL; + } + + if (DemoPlaying) + { + if (DemoFileIn == DF_ERR) + return; + + DCLOSE(DemoFileIn); + DemoFileIn = DF_ERR; + } + + if (DemoSyncTest||DemoSyncRecord) + { + fclose(DemoSyncFile); + DemoSyncFile = NULL; + } +} + +/////////////////////////////////////////// +// +// Demo Play Back +// +/////////////////////////////////////////// + + +VOID +DemoPlayBack(VOID) +{ + int pnum, cnt; + static int buf_ndx; + PLAYERp pp; + ControlInfo info; + int Xdim, Ydim, ScreenSize; + + if (SW_SHAREWARE) + { + // code here needs to be similar to RunLevel startup code + PlaySong(LevelSong, -1, TRUE, TRUE); + } + + + // Initialize Game part of network code (When ready2send != 0) + InitNetVars(); + + // IMPORTANT - MUST be right before game loop + InitTimingVars(); + + // THIS STUFF DEPENDS ON MYCONNECTINDEX BEING SET RIGHT + pp = Player + myconnectindex; + SetRedrawScreen(pp); + + if (!DemoInitOnce) + buf_ndx = 0; + + // everything has been inited at least once for PLAYBACK + DemoInitOnce = TRUE; + + cnt = 0; + ready2send = 0; + DemoDone = FALSE; + + while (TRUE) + { + // makes code run at the same rate + while (totalclock > totalsynctics) + { + handleevents(); + + TRAVERSE_CONNECT(pnum) + { + pp = Player + pnum; + pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ-1)] = DemoBuffer[buf_ndx]; + pp->movefifoend++; + buf_ndx++; + + if (pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ-1)].bits == -1) + { + DemoDone = TRUE; + break; + } + + if (buf_ndx > DEMO_BUFFER_MAX - 1) + { + DemoReadBuffer(); + buf_ndx = 0; + } + } + + if (DemoDone) + break; + + cnt++; + + CONTROL_GetInput(&info); + + domovethings(); + + MNU_CheckForMenus(); + + // fast forward and slow mo + if (DemoEdit) + { + if (KEY_PRESSED(KEYSC_F)) + { + if (KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_RSHIFT)) + totalclock += synctics; + else + totalclock += synctics-1; + } + + if (KEY_PRESSED(KEYSC_S)) + totalclock += 1-synctics; + } + else + { +#if DEBUG + if (KEY_PRESSED(KEYSC_ALT) && KEY_PRESSED(KEYSC_CTRL) && KEY_PRESSED(KEYSC_S)) + { + KEY_PRESSED(KEYSC_ALT) = KEY_PRESSED(KEYSC_CTRL) = KEY_PRESSED(KEYSC_S) = 0; + saveboard("demosave.map", &Player->posx, &Player->posy, &Player->posz, &Player->pang, &Player->cursectnum); + } +#endif + + if (BUTTON(gamefunc_See_Co_Op_View)) + { + CONTROL_ClearButton(gamefunc_See_Co_Op_View); + + screenpeek = connectpoint2[screenpeek]; + + if (screenpeek < 0) + screenpeek = connecthead; + } + +#if DEBUG + if (KEY_PRESSED(KEYSC_RIGHT) || KEY_PRESSED(KEYSC_UP)) + { + if (KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_RSHIFT)) + totalclock += synctics; + else + totalclock += synctics-1; + } + + if (KEY_PRESSED(KEYSC_LEFT) || KEY_PRESSED(KEYSC_DOWN)) + totalclock += 1-synctics; +#endif + } + + + if (DemoSyncRecord) + demosync_record(); + if (DemoSyncTest) + demosync_test(cnt); + } + + // Put this back in later when keyboard stuff is stable + if (DemoEdit) + { + //CONTROL_GetButtonInput(); + CONTROL_GetInput(&info); + + // if a key is pressed, start recording from the point the key + // was pressed + if (BUTTON(gamefunc_Move_Forward) || + BUTTON(gamefunc_Move_Backward) || + BUTTON(gamefunc_Turn_Left) || + BUTTON(gamefunc_Turn_Right) || + BUTTON(gamefunc_Fire) || + BUTTON(gamefunc_Open) || + BUTTON(gamefunc_Jump) || + BUTTON(gamefunc_Crouch) || + BUTTON(gamefunc_Look_Up) || + BUTTON(gamefunc_Look_Down)) + { + DemoBackupBuffer(); + + DemoRecCnt = buf_ndx; + DemoPlaying = FALSE; + DemoRecording = TRUE; + return; + } + } + + if (BUTTON(gamefunc_See_Co_Op_View)) + { + screenpeek += 1; + if (screenpeek > numplayers-1) + screenpeek = 0; + } + + // demo is over + if (DemoDone) + break; + + if (QuitFlag) + { + DemoMode = FALSE; + break; + } + + if (ExitLevel) + { + // Quiting Demo + ExitLevel = FALSE; + if (DemoMode) + { + DemoPlaying = FALSE; + DemoMode = FALSE; + } + break; + } + + drawscreen(Player + screenpeek); + } + + // only exit if conditions are write + if (DemoDone && !DemoMode && !NewGame) + { + TerminateLevel(); + TerminateGame(); + exit(0); + } + +} + +// +// Still using old method of playback - this was for opening demo +// + +VOID +ScenePlayBack(VOID) +{ + int buf_ndx, pnum, cnt; + PLAYERp pp; + + if (SW_SHAREWARE) + { + // code here needs to be similar to RunLevel startup code + strcpy(LevelSong,"yokoha03.mid"); + PlaySong(LevelSong, -1, TRUE, TRUE); + } + + // IMPORTANT - MUST be right before game loop + InitTimingVars(); + + buf_ndx = 0; + cnt = 0; + ready2send = 0; + DemoDone = FALSE; + + ResetKeys(); + + while (TRUE) + { + // makes code run at the same rate + while ((totalclock > totalsynctics)) + { + TRAVERSE_CONNECT(pnum) + { + pp = Player + pnum; + pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)] = DemoBuffer[buf_ndx]; + pp->movefifoend++; + buf_ndx++; + + if (pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)].bits == -1) + { + DemoDone = TRUE; + break; + } + + if (buf_ndx > DEMO_BUFFER_MAX - 1) + { + DemoReadBuffer(); + buf_ndx = 0; + } + } + + if (KeyPressed()) + DemoDone = TRUE; + + if (DemoDone) + break; + + cnt++; + + //movethings(); + domovethings(); + + MNU_CheckForMenus(); + } + + // demo is over + if (DemoDone) + break; + + drawscreen(Player + screenpeek); + } +} + + + diff --git a/polymer/eduke32/source/sw/src/demo.h b/polymer/eduke32/source/sw/src/demo.h new file mode 100644 index 000000000..51a073163 --- /dev/null +++ b/polymer/eduke32/source/sw/src/demo.h @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +extern FILE *DemoFile; +extern BOOL DemoPlaying; +extern BOOL DemoRecording; +extern BOOL DemoEdit; +extern BOOL DemoMode; +extern BOOL DemoOverride; +extern char DemoFileName[16]; +extern char DemoLevelName[16]; + +extern FILE *DemoSyncFile; +extern BOOL DemoSyncTest; +extern BOOL DemoSyncRecord; +extern char DemoTmpName[16]; + +extern BOOL DemoDebugMode; +extern BOOL DemoInitOnce; +extern short DemoDebugBufferMax; + +#define DEMO_BUFFER_MAX 2048 +extern SW_PACKET DemoBuffer[DEMO_BUFFER_MAX]; +extern int DemoRecCnt; // Can only record 1-player game + +#define DEMO_FILE_GROUP 0 +#define DEMO_FILE_STD 1 +#define DEMO_FILE_TYPE DEMO_FILE_GROUP + +// Demo File - reading from group +#if DEMO_FILE_TYPE == DEMO_FILE_GROUP +typedef long DFILE; +#define DREAD(ptr, size, num, handle) kread((handle),(ptr),(size)*(num)) +#define DOPEN_READ(name) kopen4load(name,0) +#define DCLOSE(handle) kclose(handle) +#define DF_ERR -1 +#else +typedef FILE *DFILE; +#define DREAD(ptr, size, num,handle) fread((ptr),(size),(num),(handle)) +#define DWRITE(ptr, size, num,handle) fwrite((ptr),(size),(num),(handle)) +#define DOPEN_WRITE(name) fopen(name,"wb") +#define DOPEN_READ(name) fopen(name,"rb") +#define DCLOSE(handle) fclose(handle) +#define DF_ERR NULL +#endif + +void DemoTerm(void); +void DemoPlaySetup(void); +void DemoPlayBack(void); +void ScenePlayBack(void); +void DemoRecordSetup(void); +void DemoDebugWrite(void); +void DemoWriteBuffer(void); diff --git a/polymer/eduke32/source/sw/src/digi.h b/polymer/eduke32/source/sw/src/digi.h new file mode 100644 index 000000000..bb4db16cb --- /dev/null +++ b/polymer/eduke32/source/sw/src/digi.h @@ -0,0 +1,992 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#ifdef DIGI_TABLE +#define DIGI_ENTRY(name, id, id_num, pri, pitch_lo, pitch_hi, voc_num, voc_dist, voc_flags) { name, NULL, 0, pitch_lo, pitch_hi, pri, voc_num, voc_dist, voc_flags, 0,0}, +#endif + +#ifdef DIGI_ENUM +#define DIGI_ENTRY(name, id, id_num, pri, pitch_lo, pitch_hi, voc_num, voc_dist, voc_flags) id = id_num, +#endif + +// !JIM! 09/20/95 +// NOTE: HIGHER priority numbers have the highest precedence in the play list. +#define PRI_MAX 100 +#define PRI_PLAYERDEATH 51 +#define PRI_PLAYERVOICE 50 +#define PRI_HI_PLAYERWEAP 49 +#define PRI_LOW_PLAYERWEAP 48 +#define PRI_PLAYERAMBIENT 40 +#define PRI_NPCDEATH 49 +#define PRI_NPCWEAP 47 +#define PRI_NPCATTACK 42 +#define PRI_NPCAMBIENT 39 +#define PRI_ITEM 41 +#define PRI_SWITCH PRI_MAX // To give a clue to player location +#define PRI_SECTOROBJ 30 +#define PRI_ENVIRONMENT 20 +#define PRI_AMBIENT 10 + +// Distance definitions for effective sound ranges +// Note: These are some useful constants, but you can type in whatever you want! +#define DIST_NORMAL 0 // Just play sound normaly +#define DIST_MAXNORMAL 16384 // This is max distance constant for normal sounds +// This is the limiting constant in Sound_Dist function. +#define DIST_WIDE 65536 // Half Level at full volume before sound begins to fade. +#define DIST_LEVELWIDE 131072 // Full Level + +// VOC Flag definitions +#define VF_NORMAL 0 +#define VF_LOOP 1 + +// WEAPONS //////////////////////////////////////////////////////////////////// + +// NULL Entry used to detect a sound's presence in sprite attrib structs. +DIGI_ENTRY("NULL.VOC", DIGI_NULL, 0, 0, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// SWORD +DIGI_ENTRY("SWRDSTR1.VOC", DIGI_SWORDSWOOSH, 1, PRI_HI_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +// SHURIKEN +DIGI_ENTRY("THROW.VOC", DIGI_STAR, 2, PRI_HI_PLAYERWEAP, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("STRCLNK.VOC", DIGI_STARCLINK, 3, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +//DIGI_ENTRY("STRWIZ.VOC", DIGI_STARWIZ, 4, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP ) +DIGI_ENTRY("NULL.VOC", DIGI_NULL_STARWIZ, 4, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// UZI +DIGI_ENTRY("UZIFIRE1.VOC", DIGI_UZIFIRE, 5, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RICH1.VOC", DIGI_RICHOCHET1, 6, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RICH2.VOC", DIGI_RICHOCHET2, 7, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RMVCLIP.VOC", DIGI_REMOVECLIP, 8, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RPLCLIP.VOC", DIGI_REPLACECLIP, 9, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +// SPENT SHELL HITTING FLOOR +DIGI_ENTRY("SHELL.VOC", DIGI_SHELL, 10, PRI_NPCATTACK, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +// CROSSRIOT +DIGI_ENTRY("RIOTFIR1.VOC", DIGI_RIOTFIRE, 11, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SHOTGUN.VOC", DIGI_RIOTFIRE2, 12, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIOTRLD.VOC", DIGI_RIOTRELOAD, 13, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("EXPMED.VOC", DIGI_BOLTEXPLODE, 14, PRI_HI_PLAYERWEAP, -100, 100, 0, DIST_MAXNORMAL, VF_NORMAL) +DIGI_ENTRY("RIOTWIZ.VOC", DIGI_BOLTWIZ, 15, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// 30MM GRENADE LAUNCHER +DIGI_ENTRY("40MMFIR2.VOC", DIGI_30MMFIRE, 16, PRI_HI_PLAYERWEAP, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIOTRLD.VOC", DIGI_30MMRELOAD, 17, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("40MMEXP2.VOC", DIGI_30MMEXPLODE, 18, PRI_HI_PLAYERWEAP, -100, 100, 0, DIST_WIDE, VF_NORMAL) +DIGI_ENTRY("RIOTWIZ.VOC", DIGI_30MMWIZ, 19, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// GORO HEAD +DIGI_ENTRY("GHFIR1.VOC", DIGI_HEADFIRE, 20, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GHWIZ.VOC", DIGI_HEADSHOTWIZ, 21, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("EXPSML.VOC", DIGI_HEADSHOTHIT, 22, PRI_LOW_PLAYERWEAP,-100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// MINES +DIGI_ENTRY("THROW.VOC", DIGI_MINETHROW, 23, PRI_HI_PLAYERWEAP,-100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PHITGRND.VOC", DIGI_MINEBOUNCE, 24, PRI_LOW_PLAYERWEAP,-100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("EXPLRG.VOC", DIGI_MINEBLOW, 25, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_WIDE, VF_NORMAL) +DIGI_ENTRY("STSCAN2.VOC", DIGI_MINEBEEP, 26, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// HEART ATTACK +DIGI_ENTRY("HBLOOP1.VOC", DIGI_HEARTBEAT, 27, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +//#ifndef SW_SHAREWARE +DIGI_ENTRY("HSQUEEZ1.VOC", DIGI_HEARTFIRE, 28, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +//#else +//DIGI_ENTRY("NULL.VOC", DIGI_HEARTFIRE, 28, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL ) +//#endif +DIGI_ENTRY("HRTWIZ.VOC", DIGI_HEARTWIZ, 29, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// MISSILE BATTERY +DIGI_ENTRY("RIOTFIR1.VOC", DIGI_MISSLFIRE, 30, PRI_HI_PLAYERWEAP, -75, 75, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("EXPMED.VOC", DIGI_MISSLEXP, 31, PRI_HI_PLAYERWEAP, -100, 100, 0, DIST_WIDE, VF_NORMAL) + +// RING OF FIRE SPELL +//#ifndef SW_SHAREWARE +DIGI_ENTRY("RFWIZ.VOC", DIGI_RFWIZ, 32, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +//#else +//DIGI_ENTRY("NULL.VOC", DIGI_NULL_RFWIZ, 32, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL ) +//#endif + +// NAPALM SPELL +DIGI_ENTRY("NAPFIRE.VOC", DIGI_NAPFIRE, 33, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NAPTWIZ.VOC", DIGI_NAPWIZ, 34, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("NAPPUFF.VOC", DIGI_NAPPUFF, 35, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// MAGIC MIRV SPELL +DIGI_ENTRY("MMFIRE.VOC", DIGI_MIRVFIRE, 36, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MMWIZ.VOC", DIGI_MIRVWIZ, 37, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SPIRAL SPELL +DIGI_ENTRY("SPRLFIRE.VOC", DIGI_SPIRALFIRE, 38, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPRLWIZ.VOC", DIGI_SPIRALWIZ, 39, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// MAGIC SOUNDS, GENERIC +// (USED FOR MAGIC CARPET RIDES,ETC.) +DIGI_ENTRY("MAGIC1.VOC", DIGI_MAGIC1, 40, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MAGIC2.VOC", DIGI_MAGIC2, 41, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MAGIC3.VOC", DIGI_MAGIC3, 42, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MAGIC4.VOC", DIGI_MAGIC4, 43, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MAGIC5.VOC", DIGI_MAGIC5, 44, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MAGIC6.VOC", DIGI_MAGIC6, 45, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MAGIC7.VOC", DIGI_MAGIC7, 46, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// SHADOW WARRIOR SPELL +//#ifndef SW_SHAREWARE +DIGI_ENTRY("SWSPELL.VOC", DIGI_SWCLOAKUNCLOAK, 47, PRI_LOW_PLAYERWEAP,-100, 100, 0, DIST_NORMAL, VF_NORMAL) +//#else +//DIGI_ENTRY("NULL.VOC", DIGI_NULL_SWCLOAK, 47, PRI_LOW_PLAYERWEAP,-100, 100, 0, DIST_NORMAL, VF_NORMAL ) +//#endif + +// PLAYER DEAD HEAD +DIGI_ENTRY("DHVOMIT.VOC", DIGI_DHVOMIT, 48, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("DHCLUNK.VOC", DIGI_DHCLUNK, 49, PRI_PLAYERAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +//DIGI_ENTRY("DHSQSH.VOC", DIGI_DHSQUISH, 50, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL ) +DIGI_ENTRY("NULL.VOC", DIGI_NULL_DHSQUISH, 50, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// WEAPON RELATED +DIGI_ENTRY("LAVAHIT.VOC", DIGI_PROJECTILELAVAHIT,51, PRI_PLAYERAMBIENT,-100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("STSPL01.VOC", DIGI_PROJECTILEWATERHIT,52, PRI_PLAYERAMBIENT,-100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// ITEMS +DIGI_ENTRY("KEY.VOC", DIGI_KEY, 53, PRI_ITEM, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ITEM5A.VOC", DIGI_ITEM, 54, PRI_ITEM, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ITEMBIG2.VOC", DIGI_BIGITEM, 55, PRI_ITEM, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// DEATH/HURT +DIGI_ENTRY("BODY9.VOC", DIGI_BODYFALL1, 56, PRI_PLAYERDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PHITGRND.VOC", DIGI_HITGROUND, 57, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BODY2.VOC", DIGI_BODYSQUISH1, 58, PRI_PLAYERAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BURN1.VOC", DIGI_BODYBURN, 59, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BURNSCRM.VOC", DIGI_BODYBURNSCREAM, 60, PRI_PLAYERDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BODY3.VOC", DIGI_BODYCRUSHED1, 61, PRI_PLAYERAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BODY4.VOC", DIGI_BODYHACKED1, 62, PRI_PLAYERAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BURN2.VOC", DIGI_BODYSINGED, 63, PRI_PLAYERAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("DROWN1.VOC", DIGI_DROWN, 64, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SCREAM1.VOC", DIGI_SCREAM1, 65, PRI_PLAYERDEATH, -200, 400, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SCREAM2.VOC", DIGI_SCREAM2, 66, PRI_PLAYERDEATH, -200, 400, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SCREAM3.VOC", DIGI_SCREAM3, 67, PRI_PLAYERDEATH, -200, 400, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HIT1.VOC", DIGI_HIT1, 68, PRI_LOW_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ELECTRC1.VOC", DIGI_ELECTRICUTE1, 69, PRI_PLAYERAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWDIE02.VOC", DIGI_REMOVEME, 70, PRI_PLAYERDEATH, -200, 500, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("IMPALE1.VOC", DIGI_IMPALED, 71, PRI_PLAYERDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("OOF1.VOC", DIGI_OOF1, 72, PRI_PLAYERAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +// ACTOR SOUNDS THAT USER +// PLAYER SOUNDS AT A LOWER PRIORITY +DIGI_ENTRY("BODY1.VOC", DIGI_ACTORBODYFALL1, 73, PRI_NPCWEAP, 0, 0, DIGI_BODYFALL1, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HITGRND.VOC", DIGI_ACTORHITGROUND, 74, PRI_NPCWEAP, 0, 0, DIGI_HITGROUND, DIST_NORMAL, VF_NORMAL) + +// NPC'S ////////////////////////////////////////////////////////////////////// + +// COOLIE +DIGI_ENTRY("COLEXP.VOC", DIGI_COOLIEEXPLODE, 75, PRI_NPCDEATH, -100, 100, 0, DIST_MAXNORMAL, VF_NORMAL) +DIGI_ENTRY("COLSCRM.VOC", DIGI_COOLIESCREAM, 76, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("COLALRT.VOC", DIGI_COOLIEALERT, 77, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("COLAMB.VOC", DIGI_COOLIEAMBIENT, 78, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("COLPAIN.VOC", DIGI_COOLIEPAIN, 79, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// COOLIE GHOST +DIGI_ENTRY("CGMAT.VOC", DIGI_CGMATERIALIZE, 80, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGALRT.VOC", DIGI_CGALERT, 81, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGWHACK.VOC", DIGI_CGTHIGHBONE, 82, PRI_NPCWEAP, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGAMB.VOC", DIGI_CGAMBIENT, 83, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGPAIN.VOC", DIGI_CGPAIN, 84, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGSHOOT.VOC", DIGI_CGMAGIC, 85, PRI_NPCWEAP, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGHIT.VOC", DIGI_CGMAGICHIT, 86, PRI_NPCWEAP, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CGSCRM.VOC", DIGI_CGSCREAM, 87, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// NINJA +DIGI_ENTRY("NINAMB.VOC", DIGI_NINJAAMBIENT, 88, PRI_NPCAMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NINSTAR.VOC", DIGI_NINJASTAR, 89, PRI_NPCWEAP, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NINPAIN.VOC", DIGI_NINJAPAIN, 90, PRI_NPCWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NINSCRM.VOC", DIGI_NINJASCREAM, 91, PRI_NPCDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NINALRT.VOC", DIGI_NINJAALERT, 92, PRI_NPCATTACK, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NINSHOOT.VOC", DIGI_NINJAUZIATTACK, 93, PRI_NPCWEAP, 0, 0, DIGI_UZIFIRE, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIOTFIR1.VOC", DIGI_NINJARIOTATTACK, 94, PRI_NPCWEAP, 0, 0, DIGI_RIOTFIRE, DIST_NORMAL, VF_NORMAL) + +// RIPPER +DIGI_ENTRY("RIPAMB.VOC", DIGI_RIPPERAMBIENT, 95, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIPALRT.VOC", DIGI_RIPPERALERT, 96, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIPATCK.VOC", DIGI_RIPPERATTACK, 97, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIPPAIN.VOC", DIGI_RIPPERPAIN, 98, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIPSCRM.VOC", DIGI_RIPPERSCREAM, 99, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIPHRT.VOC", DIGI_RIPPERHEARTOUT, 100, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// GUARDIAN +DIGI_ENTRY("GRDAMB.VOC", DIGI_GRDAMBIENT, 101, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GRDALRT.VOC", DIGI_GRDALERT, 102, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GRDPAIN.VOC", DIGI_GRDPAIN, 103, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GRDSCRM.VOC", DIGI_GRDSCREAM, 104, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GRDFIR.VOC", DIGI_GRDFIREBALL, 105, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GRDAXE.VOC", DIGI_GRDSWINGAXE, 106, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GRDAXHT.VOC", DIGI_GRDAXEHIT, 107, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// SKELETOR PRIEST +DIGI_ENTRY("SPAMB.VOC", DIGI_SPAMBIENT, 108, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPALRT.VOC", DIGI_SPALERT, 109, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPPAIN.VOC", DIGI_SPPAIN, 110, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPSCRM.VOC", DIGI_SPSCREAM, 111, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPBLADE.VOC", DIGI_SPBLADE, 112, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPELEC.VOC", DIGI_SPELEC, 113, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPTLPRT.VOC", DIGI_SPTELEPORT, 114, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// ACCURSED HEAD +DIGI_ENTRY("AHAMB.VOC", DIGI_AHAMBIENT, 115, PRI_NPCAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AHSCRM.VOC", DIGI_AHSCREAM, 116, PRI_NPCDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AHEXP.VOC", DIGI_AHEXPLODE, 117, PRI_NPCDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AHSHWSH.VOC", DIGI_AHSWOOSH, 118, PRI_NPCATTACK, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// HORNET +DIGI_ENTRY("HBUZZ.VOC", DIGI_HORNETBUZZ, 119, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("HSTING.VOC", DIGI_HORNETSTING, 120, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HPAIN.VOC", DIGI_HORNETPAIN, 121, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HDEATH.VOC", DIGI_HORNETDEATH, 122, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// SERPENT GOD BOSS +DIGI_ENTRY("SGAMB.VOC", DIGI_SERPAMBIENT, 123, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGALRT.VOC", DIGI_SERPALERT, 124, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGPAIN.VOC", DIGI_SERPPAIN, 125, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGSCRM.VOC", DIGI_SERPSCREAM, 126, PRI_MAX, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGDETH.VOC", DIGI_SERPDEATHEXPLODE,127, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGSWORD.VOC", DIGI_SERPSWORDATTACK, 128, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGMAGIC.VOC", DIGI_SERPMAGICLAUNCH, 129, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGHEADS.VOC", DIGI_SERPSUMMONHEADS, 130, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGTAUNT.VOC", DIGI_SERPTAUNTYOU, 131, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// LAVA BOSS +DIGI_ENTRY("LVAMB.VOC", DIGI_LAVABOSSAMBIENT, 132, PRI_NPCAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVSWIM.VOC", DIGI_LAVABOSSSWIM, 133, PRI_NPCAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVRISE.VOC", DIGI_LAVABOSSRISE, 134, PRI_NPCAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVALRT.VOC", DIGI_LAVABOSSALERT, 135, PRI_NPCATTACK, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVFLAME.VOC", DIGI_LAVABOSSFLAME, 136, PRI_NPCATTACK, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVMETEOR.VOC", DIGI_LAVABOSSMETEOR, 137, PRI_NPCATTACK, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVMETEXP.VOC", DIGI_LAVABOSSMETEXP, 138, PRI_NPCATTACK, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVPAIN.VOC", DIGI_LAVABOSSPAIN, 139, PRI_NPCATTACK, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVSIZZLE.VOC", DIGI_LAVABOSSSIZZLE, 140, PRI_NPCAMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LVEXPL.VOC", DIGI_LAVABOSSEXPLODE, 141, PRI_NPCDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// LEVEL AND SECTOR OBJECT SOUNDS /////////// + +// MOTOR BOAT +DIGI_ENTRY("BTSTRT.VOC", DIGI_BOATSTART, 142, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BTRUN01.VOC", DIGI_BOATRUN, 143, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("BTSTOP.VOC", DIGI_BOATSTOP, 144, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BTFIRE.VOC", DIGI_BOATFIRE, 145, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// ARMY TANK +DIGI_ENTRY("TNKSTRT.VOC", DIGI_TANKSTART, 146, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TNKRUN.VOC", DIGI_TANKRUN, 147, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("TNKSTOP.VOC", DIGI_TANKSTOP, 148, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TNKIDLE.VOC", DIGI_TANKIDLE, 149, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("TNKFIRE.VOC", DIGI_TANKFIRE, 150, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// ARMY TRUCK +DIGI_ENTRY("TRUKRUN.VOC", DIGI_TRUKRUN, 151, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("TRUKIDLE.VOC", DIGI_TRUKIDLE, 152, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SUBMARINE +DIGI_ENTRY("SUBRUN.VOC", DIGI_SUBRUN, 153, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("SUBIDLE.VOC", DIGI_SUBIDLE, 154, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("SUBDOOR.VOC", DIGI_SUBDOOR, 155, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// WWII JAP BOMBER PLANE +DIGI_ENTRY("BMBFLY.VOC", DIGI_BOMBRFLYING, 156, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("BMBDROP.VOC", DIGI_BOMBRDROPBOMB, 157, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// BUBBLES +DIGI_ENTRY("BUBBLE.VOC", DIGI_BUBBLES, 158, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// CHAIN MOVING +// SOUND NOT AVAILABLE -- DELTED +DIGI_ENTRY("CHAIN.VOC", DIGI_CHAIN, 159, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// CHAIN DOOR +DIGI_ENTRY("CHNDOOR.VOC", DIGI_CHAINDOOR, 160, PRI_ENVIRONMENT, 0, 0, 0, 8000, VF_NORMAL) + +// CRICKETS +DIGI_ENTRY("CRCKT2.VOC", DIGI_CRICKETS, 161, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// WOOD DOOR OPEN/CLOSE +DIGI_ENTRY("DRWOODO.VOC", DIGI_WOODDOOROPEN, 162, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) +DIGI_ENTRY("DRWOODC.VOC", DIGI_WOODDOORCLOSE, 163, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) + +// METAL DOOR OPEN/CLOSE +DIGI_ENTRY("DRMETO.VOC", DIGI_METALDOOROPEN, 164, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) +DIGI_ENTRY("DRMETC.VOC", DIGI_METALDOORCLOSE, 165, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) + +// SLIDING DOOR OPEN/CLOSE +DIGI_ENTRY("DRSLDO.VOC", DIGI_SLIDEDOOROPEN, 166, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) +DIGI_ENTRY("DRSLDC.VOC", DIGI_SLIDEDOORCLOSE, 167, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) + +// STONE SLIDING DOOR OPEN/CLOSE +DIGI_ENTRY("DRSTNO.VOC", DIGI_STONEDOOROPEN, 168, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) +DIGI_ENTRY("DRSTNC.VOC", DIGI_STONEDOORCLOSE, 169, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) + +// SQUEAKY DOOR OPEN/CLOSE +DIGI_ENTRY("DRSQKO.VOC", DIGI_SQUEAKYDOOROPEN, 170, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) +DIGI_ENTRY("DRSQKC.VOC", DIGI_SQUEAKYDOORCLOSE,171, PRI_ENVIRONMENT, -100, 100, 0, 8000, VF_NORMAL) + +// GIANT DRILL MACHINE +DIGI_ENTRY("DRILL.VOC", DIGI_DRILL, 172, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// AMBIENT WATER DRIPPING IN CAVE +DIGI_ENTRY("CAVE1.VOC", DIGI_CAVEDRIP1, 173, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("CAVE2.VOC", DIGI_CAVEDRIP2, 174, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +DIGI_ENTRY("DRIP.VOC", DIGI_DRIP, 175, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// WATER FALL +DIGI_ENTRY("WTRFAL1.VOC", DIGI_WATERFALL1, 176, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +// THERE IS NO WTRFAL2 -- DELETED!!! +DIGI_ENTRY("WTRFAL2.VOC", DIGI_WATERFALL2, 177, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// WATER FLOWING +DIGI_ENTRY("WTRFLW1.VOC", DIGI_WATERFLOW1, 178, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) +// THERE IS NO WTRFLW2 -- DELETED!!! +DIGI_ENTRY("WTRFLW2.VOC", DIGI_WATERFLOW2, 179, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// ELEVATOR START/STOP +DIGI_ENTRY("ELEV1.VOC", DIGI_ELEVATOR, 180, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// SMALL EXP +DIGI_ENTRY("EXPSML.VOC", DIGI_SMALLEXP, 181, PRI_ENVIRONMENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +// MEDIUM EXP +DIGI_ENTRY("EXPMED.VOC", DIGI_MEDIUMEXP, 182, PRI_ENVIRONMENT, -200, 200, 0, DIST_WIDE, VF_NORMAL) + +// LARGE EXP +DIGI_ENTRY("EXPLRG.VOC", DIGI_LARGEEXP, 183, PRI_ENVIRONMENT, -200, 200, 0, DIST_WIDE, VF_NORMAL) + +// HUGE EXP +//DIGI_ENTRY("BIGEXP.VOC", DIGI_HUGEEXP, 184, PRI_ENVIRONMENT, -200, 200, 0, DIST_WIDE, VF_NORMAL ) +DIGI_ENTRY("NULL.VOC", DIGI_NULL_HUGEEXP, 184, PRI_ENVIRONMENT, -200, 200, 0, DIST_WIDE, VF_NORMAL) + +// CRACKLING FIRE FOR CONTINUOUS BURN +DIGI_ENTRY("FIRE1.VOC", DIGI_FIRE1, 185, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// POWERFULL HIGH HEAT CONTINUOUS BURN +DIGI_ENTRY("FIRE2.VOC", DIGI_FIRE2, 186, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SHOOTING FIREBALL FOR FIREBALL TRAP +DIGI_ENTRY("FBALL1.VOC", DIGI_FIREBALL1, 187, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SHOOTING FIREBALL FOR FIREBALL TRAP +DIGI_ENTRY("FIREBALL1.VOC", DIGI_FIREBALL2, 188, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SECTOR GEAR COG TURNING +DIGI_ENTRY("GEAR1.VOC", DIGI_GEAR1, 189, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// AMBIENT GONG FOR USE IN TEMPLE/PALACE LEVELS +DIGI_ENTRY("GONG.VOC", DIGI_GONG, 190, PRI_HI_PLAYERWEAP,-100, 100, 0, 32336, VF_NORMAL) + +// AMBIENT LAVA FLOW +DIGI_ENTRY("LAVAFLW1.VOC", DIGI_LAVAFLOW1, 191, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// GENERIC SECTOR OBJECT MACHINE RUNNING +DIGI_ENTRY("MACHN1.VOC", DIGI_MACHINE1, 192, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// AMBIENT MUD BUBBLES +DIGI_ENTRY("MUD1.VOC", DIGI_MUBBUBBLES1, 193, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// AMBIENT EARTH QUAKE +DIGI_ENTRY("QUAKE1.VOC", DIGI_EARTHQUAKE, 194, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// YUCKY SEWER FLOW +DIGI_ENTRY("SEWER1.VOC", DIGI_SEWERFLOW1, 195, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// WATER SPLASHING +//(USE FOR PLAYER/NPC'S JUMPING AROUND IN WATER) +DIGI_ENTRY("SPLASH1.VOC", DIGI_SPLASH1, 196, PRI_ENVIRONMENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// STEAM FLOW +DIGI_ENTRY("STEAM1.VOC", DIGI_STEAM1, 197, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// VOLCANIC STEAM VENT +DIGI_ENTRY("VOLSTM1.VOC", DIGI_VOLCANOSTEAM1, 198, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// STOMPER THUD SECTOR OBJECT +DIGI_ENTRY("STMPR.VOC", DIGI_STOMPER, 199, PRI_SECTOROBJ, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// SCARY AMBIENT SWAMP SOUNDS +DIGI_ENTRY("SWAMP1.VOC", DIGI_SWAMP, 200, PRI_AMBIENT, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// FLIP SWITCH +DIGI_ENTRY("SWITCH1.VOC", DIGI_REGULARSWITCH, 201, PRI_ENVIRONMENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// FLIP LARGE SWITCH +DIGI_ENTRY("SWITCH2.VOC", DIGI_BIGSWITCH, 202, PRI_ENVIRONMENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// STONE SWITCH +DIGI_ENTRY("SWITCH3.VOC", DIGI_STONESWITCH, 203, PRI_ENVIRONMENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// BREAKABLE GLASS SWITCH +DIGI_ENTRY("SWITCH4.VOC", DIGI_GLASSSWITCH, 204, PRI_ENVIRONMENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// HUGE ECHOING SWITCH +DIGI_ENTRY("SWITCH5.VOC", DIGI_HUGESWITCH, 205, PRI_ENVIRONMENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// AMBIENT ROLLING THUNDER +DIGI_ENTRY("THUNDR.VOC", DIGI_THUNDER, 206, PRI_AMBIENT, -200, 200, 0, DIST_LEVELWIDE, VF_NORMAL) + +// TELEPORTER +DIGI_ENTRY("TELPORT.VOC", DIGI_TELEPORT, 207, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// UNDERWATER AMBIENCE +DIGI_ENTRY("UNDRWTR.VOC", DIGI_UNDERWATER, 208, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// UNLOCK BIG LOCKED DOOR +DIGI_ENTRY("UNLOCK.VOC", DIGI_UNLOCK, 209, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// SQUEAKY VALVE TURNING +DIGI_ENTRY("VALVE.VOC", DIGI_SQUEAKYVALVE, 210, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// SPOOKY ETHERAL VOID AMBIENCE +//(NETHERWORLDLY SOUNDS) +DIGI_ENTRY("VOID1.VOC", DIGI_VOID1, 211, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("VOID2.VOC", DIGI_VOID2, 212, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("VOID3.VOC", DIGI_VOID3, 213, PRI_NPCWEAP, 0, 0, 0, -8000, VF_NORMAL) +DIGI_ENTRY("VOID4.VOC", DIGI_VOID4, 214, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("VOID5.VOC", DIGI_VOID5, 215, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// VOLCANIC ERUPTION +DIGI_ENTRY("ERUPT.VOC", DIGI_ERUPTION, 216, PRI_AMBIENT, 0, 0, 0, DIST_MAXNORMAL, VF_LOOP) + +// VOLCANIC SIZZLING PROJECTILES FLYING THROUGH AIR +DIGI_ENTRY("VOLPRJCT.VOC", DIGI_VOLCANOPROJECTILE, 217, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// LIGHT WIND AMBIENCE +DIGI_ENTRY("WIND1.VOC", DIGI_LIGHTWIND, 218, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// STRONG BLOWING WIND AMBIENCE +DIGI_ENTRY("WIND2.VOC", DIGI_STRONGWIND, 219, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// BREAKING WOOD AMBIENCE +DIGI_ENTRY("WOODBRK.VOC", DIGI_BREAKINGWOOD, 220, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// BREAKING, TUMBLING STONES FALLING AMBIENCE +DIGI_ENTRY("STONEBRK.VOC", DIGI_BREAKSTONES, 221, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// ENGINE ROOM SOUND +DIGI_ENTRY("ENGROOM1.VOC", DIGI_ENGROOM1, 222, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("ENGROOM2.VOC", DIGI_ENGROOM2, 223, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("ENGROOM3.VOC", DIGI_ENGROOM3, 224, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("ENGROOM4.VOC", DIGI_ENGROOM4, 225, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("ENGROOM5.VOC", DIGI_ENGROOM5, 226, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// BREAKING GLASS, LARGE WINDOW PANE +DIGI_ENTRY("GLASS3.VOC", DIGI_BREAKGLASS, 227, PRI_NPCDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// MUSICAL STINGER +DIGI_ENTRY("MUSSTING.VOC", DIGI_MUSSTING, 228, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// HELICOPTER LIKE SOUND +DIGI_ENTRY("HELI.VOC", DIGI_HELI, 229, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// HUGE ECHOING HEART LIKE AMBIENCE +DIGI_ENTRY("BIGHART.VOC", DIGI_BIGHART, 230, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// EERIE ETHERAL TYPE WIND +DIGI_ENTRY("WIND4.VOC", DIGI_WIND4, 231, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SPOOKY SINE WAVE SOUND +DIGI_ENTRY("SPOOKY1.VOC", DIGI_SPOOKY1, 232, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// SPOOKY SINE WAVE SOUND +DIGI_ENTRY("DRILL1.VOC", DIGI_DRILL1, 233, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +// JET ENGINE +DIGI_ENTRY("JET.VOC", DIGI_JET, 234, PRI_AMBIENT, 0, 0, 0, DIST_MAXNORMAL, VF_LOOP) + +// CERIMONIAL DRUM CHANT +DIGI_ENTRY("DRUMCHNT.VOC", DIGI_DRUMCHANT, 235, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +DIGI_ENTRY("FLY.VOC", DIGI_BUZZZ, 236, PRI_MAX, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("UZICLK.VOC", DIGI_CHOP_CLICK, 237, PRI_MAX, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// !IMPORTANT! Make sure all player voices stay together +DIGI_ENTRY("STICKY2R.VOC", DIGI_SWORD_UP, 238, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("UZI1R.VOC", DIGI_UZI_UP, 239, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SHOTG1R.VOC", DIGI_SHOTGUN_UP, 240, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BOLT1R.VOC", DIGI_ROCKET_UP, 241, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BOLT1R.VOC", DIGI_GRENADE_UP, 242, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BOLT1R.VOC", DIGI_RAIL_UP, 243, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("STICKY1R.VOC", DIGI_MINE_UP, 244, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("", DIGI_FIRSTPLAYERVOICE,245, 0, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BADMAN04.VOC", DIGI_TAUNTAI1, 246, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("COMEGET2.VOC", DIGI_TAUNTAI2, 247, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GHOP07.VOC", DIGI_TAUNTAI3, 248, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GOODDAY4.VOC", DIGI_TAUNTAI4, 249, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("KILLU05.VOC", DIGI_TAUNTAI5, 250, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NATURAL4.VOC", DIGI_TAUNTAI6, 251, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NOHONOR6.VOC", DIGI_TAUNTAI7, 252, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SAYON09.VOC", DIGI_TAUNTAI8, 253, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TAKSAN1.VOC", DIGI_TAUNTAI9, 254, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SNATCH01.VOC", DIGI_TAUNTAI10, 255, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("CHOTO7.VOC", DIGI_PLAYERPAIN1, 256, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWPAIN05.VOC", DIGI_PLAYERPAIN2, 257, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWPAIN03.VOC", DIGI_PLAYERPAIN3, 258, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWPAIN07.VOC", DIGI_PLAYERPAIN4, 259, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWPAIN22.VOC", DIGI_PLAYERPAIN5, 260, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("SWYELL03.VOC", DIGI_PLAYERYELL1, 261, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL05.VOC", DIGI_PLAYERYELL2, 262, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL06.VOC", DIGI_PLAYERYELL3, 263, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("GRUNT06.VOC", DIGI_SEARCHWALL, 264, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("NOWAY1.VOC", DIGI_NOURINAL, 265, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("SWDIE02.VOC", DIGI_FALLSCREAM, 266, PRI_PLAYERDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AHSO5.VOC", DIGI_GOTITEM1, 267, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("", DIGI_LASTPLAYERVOICE, 268, 0, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +//#ifndef SW_SHAREWARE +// was RAILB10.VOC +DIGI_ENTRY("HSHOT1.VOC", DIGI_RAILFIRE, 269, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +//#else +//DIGI_ENTRY("NULL.VOC", DIGI_NULL_RAILFIRE, 269, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL ) +//#endif +DIGI_ENTRY("RAIL2.VOC", DIGI_RAILREADY, 270, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("RAILUP09.VOC", DIGI_RAILPWRUP, 271, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("HBOMB2.VOC", DIGI_NUCLEAREXP, 272, PRI_MAX, 0, 0, 0, DIST_LEVELWIDE, VF_NORMAL) +DIGI_ENTRY("STANDBY.VOC", DIGI_NUKESTDBY, 273, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CDOWN.VOC", DIGI_NUKECDOWN, 274, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SYSREAD.VOC", DIGI_NUKEREADY, 275, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("HISS1.VOC", DIGI_CHEMGAS, 276, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("CHBNCE1.VOC", DIGI_CHEMBOUNCE, 277, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("THROW.VOC", DIGI_THROW, 278, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PULL.VOC", DIGI_PULL, 279, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("STSCAN2.VOC", DIGI_MINEARM, 280, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HBDOWN1.VOC", DIGI_HEARTDOWN, 281, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +//DIGI_ENTRY("TOOLUSE1.VOC", DIGI_TOOLBOX, 282, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL ) +DIGI_ENTRY("NULL.VOC", DIGI_NULL_TOOLBOX, 282, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GASPOP.VOC", DIGI_GASPOP, 283, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("40MMBNCE.VOC", DIGI_40MMBNCE, 284, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BURGALRM.VOC", DIGI_BURGLARALARM, 285, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("CARALRM2.VOC", DIGI_CARALARM, 286, PRI_LOW_PLAYERWEAP, 0, 0, 0, 25000, VF_NORMAL) +DIGI_ENTRY("CAOFF1.VOC", DIGI_CARALARMOFF, 287, PRI_LOW_PLAYERWEAP, 0, 0, 0, 25000, VF_NORMAL) +DIGI_ENTRY("TACK1.VOC", DIGI_CALTROPS, 288, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NVON3.VOC", DIGI_NIGHTON, 289, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NVOFF2.VOC", DIGI_NIGHTOFF, 290, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SGSH01.VOC", DIGI_SHOTSHELLSPENT, 291, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SKID3.VOC", DIGI_BUSSKID, 292, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CRASH4.VOC", DIGI_BUSCRASH, 293, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BUS1.VOC", DIGI_BUSENGINE, 294, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BIMP01.VOC", DIGI_ARMORHIT, 295, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("ASIREN1.VOC", DIGI_ASIREN1, 296, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("FIRETRK1.VOC", DIGI_FIRETRK1, 297, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAFFIC1.VOC", DIGI_TRAFFIC1, 298, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAFFIC2.VOC", DIGI_TRAFFIC2, 299, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAFFIC3.VOC", DIGI_TRAFFIC3, 300, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAFFIC4.VOC", DIGI_TRAFFIC4, 301, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAFFIC5.VOC", DIGI_TRAFFIC5, 302, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAFFIC6.VOC", DIGI_TRAFFIC6, 303, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HELI1.VOC", DIGI_HELI1, 304, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JET1.VOC", DIGI_JET1, 305, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MOTO1.VOC", DIGI_MOTO1, 306, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MOTO2.VOC", DIGI_MOTO2, 307, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NEON1.VOC", DIGI_NEON1, 308, PRI_AMBIENT, 0, 0, 0, -8000, VF_NORMAL) +DIGI_ENTRY("SUBWAY1.VOC", DIGI_SUBWAY, 309, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAINS01.VOC", DIGI_TRAIN1, 310, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("COIN.VOC", DIGI_COINS, 311, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWRDSMK1.VOC", DIGI_SWORDCLANK, 312, PRI_HI_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +// RIPPER2 +DIGI_ENTRY("RIP2AMB.VOC", DIGI_RIPPER2AMBIENT, 313, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIP2ALRT.VOC", DIGI_RIPPER2ALERT, 314, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIP2ATCK.VOC", DIGI_RIPPER2ATTACK, 315, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIP2PAIN.VOC", DIGI_RIPPER2PAIN, 316, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIP2SCRM.VOC", DIGI_RIPPER2SCREAM, 317, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIP2HRT.VOC", DIGI_RIPPER2HEARTOUT,318, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("M60.VOC", DIGI_M60, 319, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// SUMO +DIGI_ENTRY("SUMSCRM.VOC", DIGI_SUMOSCREAM, 320, PRI_MAX, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SUMALRT.VOC", DIGI_SUMOALERT, 321, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SUMAMB.VOC", DIGI_SUMOAMBIENT, 322, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SUMPAIN.VOC", DIGI_SUMOPAIN, 323, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +// UNLOCK RAM LOCKED DOOR +DIGI_ENTRY("RAMLOCK.VOC", DIGI_RAMUNLOCK, 324, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +// UNLOCK CARD LOCKED DOOR +DIGI_ENTRY("CARDLOCK.VOC", DIGI_CARDUNLOCK, 325, PRI_ENVIRONMENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// More player voices +DIGI_ENTRY("ACS10.VOC", DIGI_ANCIENTSECRET, 326, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AMDRIV01.VOC", DIGI_AMERICANDRIVER, 327, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BABOON03.VOC", DIGI_DRIVELIKEBABOON, 328, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BBURN04.VOC", DIGI_BURNBABY, 329, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BIGWPN01.VOC", DIGI_LIKEBIGWEAPONS, 330, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CBUNG01.VOC", DIGI_COWABUNGA, 331, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CHARAD09.VOC", DIGI_NOCHARADE, 332, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("DTIME.VOC", DIGI_TIMETODIE, 333, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("EAT02.VOC", DIGI_EATTHIS, 334, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("FCRACK01.VOC", DIGI_FIRECRACKERUPASS,335, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HCOW03.VOC", DIGI_HOLYCOW, 336, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HCOW06.VOC", DIGI_HOLYPEICESOFCOW, 337, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HSHIT03.VOC", DIGI_HOLYSHIT, 338, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HSHIT04.VOC", DIGI_HOLYPEICESOFSHIT,339, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("IHOPE01.VOC", DIGI_PAYINGATTENTION, 340, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ILIKE01.VOC", DIGI_EVERYBODYDEAD, 341, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("KUNGFU06.VOC", DIGI_KUNGFU, 342, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LMOVE01.VOC", DIGI_HOWYOULIKEMOVE, 343, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LWANG05.VOC", DIGI_NOMESSWITHWANG, 344, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RAW01.VOC", DIGI_RAWREVENGE, 345, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("STUPID01.VOC", DIGI_YOULOOKSTUPID, 346, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TDICK02.VOC", DIGI_TINYDICK, 347, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TOURN01.VOC", DIGI_NOTOURNAMENT, 348, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("WWANG11.VOC", DIGI_WHOWANTSWANG, 349, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("YAK02.VOC", DIGI_MOVELIKEYAK, 350, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("REFLEX08.VOC", DIGI_ALLINREFLEXES, 351, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("EVADE01.VOC", DIGI_EVADEFOREVER, 352, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MFLY03.VOC", DIGI_MRFLY, 353, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SHISEI03.VOC", DIGI_SHISEISI, 354, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("FWORKS01.VOC", DIGI_LIKEFIREWORKS, 355, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HIRO03.VOC", DIGI_LIKEHIROSHIMA, 356, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NAGA06.VOC", DIGI_LIKENAGASAKI, 357, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PEARL03.VOC", DIGI_LIKEPEARL, 358, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("IAM01.VOC", DIGI_IAMSHADOW, 359, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LIKNUK01.VOC", DIGI_ILIKENUKES, 360, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LIKSRD01.VOC", DIGI_ILIKESWORD, 361, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LIKSHK02.VOC", DIGI_ILIKESHURIKEN, 362, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LUCK06.VOC", DIGI_BADLUCK, 363, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MCHAN01.VOC", DIGI_NOMOVIEMRCHAN, 364, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RCHAN13.VOC", DIGI_REALLIFEMRCHAN, 365, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MUSIC03.VOC", DIGI_NOLIKEMUSIC, 366, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NODIFF07.VOC", DIGI_NODIFFERENCE, 367, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NOFEAR01.VOC", DIGI_NOFEAR, 368, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("NOPAIN.VOC", DIGI_NOPAIN, 369, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("REPMAN15.VOC", DIGI_NOREPAIRMAN, 370, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SOB15.VOC", DIGI_SONOFABITCH, 371, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("WEAK03.VOC", DIGI_PAINFORWEAK, 372, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SPEED04.VOC", DIGI_GOSPEEDY, 373, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("STIFF01.VOC", DIGI_GETTINGSTIFF, 374, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TOMB05.VOC", DIGI_TOMBRAIDER, 375, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSTICK01.VOC", DIGI_STICKYGOTU1, 376, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSTICK05.VOC", DIGI_STICKYGOTU2, 377, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSTICK07.VOC", DIGI_STICKYGOTU3, 378, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSTICK10.VOC", DIGI_STICKYGOTU4, 379, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSWORD05.VOC", DIGI_SWORDGOTU1, 380, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSWORD08.VOC", DIGI_SWORDGOTU2, 381, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TSWORD01.VOC", DIGI_SWORDGOTU3, 382, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL22.VOC", DIGI_HURTBAD1, 383, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL14.VOC", DIGI_HURTBAD2, 384, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL23.VOC", DIGI_HURTBAD3, 385, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL16.VOC", DIGI_HURTBAD4, 386, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SWYELL13.VOC", DIGI_HURTBAD5, 387, PRI_PLAYERVOICE, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +// TOILETGIRL +DIGI_ENTRY("TGSCRM.VOC", DIGI_TOILETGIRLSCREAM, 388, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TGALRT.VOC", DIGI_TOILETGIRLALERT, 389, PRI_NPCATTACK, -300, 300, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TGAMB.VOC", DIGI_TOILETGIRLAMBIENT,390, PRI_NPCAMBIENT, -300, 300, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TGPAIN.VOC", DIGI_TOILETGIRLPAIN, 391, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TGTNT1.VOC", DIGI_TOILETGIRLTAUNT1, 392, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TGTNT2.VOC", DIGI_TOILETGIRLTAUNT2, 393, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +// MORE SUMO +DIGI_ENTRY("SUMOFART.VOC", DIGI_SUMOFART, 394, PRI_PLAYERVOICE, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("GIBS04.VOC", DIGI_GIBS1, 395, PRI_LOW_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GIBS05.VOC", DIGI_GIBS2, 396, PRI_LOW_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("BIRDS01.VOC", DIGI_BIRDS1, 397, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BIRDS02.VOC", DIGI_BIRDS2, 398, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TOILET01.VOC", DIGI_TOILET, 399, PRI_AMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("FLIDLE.VOC", DIGI_FORKLIFTIDLE, 400, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("FLRUN01.VOC", DIGI_FORKLIFTRUN, 401, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TOYCAR03.VOC", DIGI_TOYCAR, 402, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("PRESS03.VOC", DIGI_UZIMATIC, 403, PRI_AMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("COMPON01.VOC", DIGI_COMPUTERPOWER, 404, PRI_LOW_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TURBON01.VOC", DIGI_GENERATORON, 405, PRI_LOW_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TURBRN01.VOC", DIGI_GENERATORRUN, 406, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("BIGDRL03.VOC", DIGI_BIGDRILL, 407, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("FLUOR01.VOC", DIGI_FLUORLIGHT, 408, PRI_AMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AMOEBA03.VOC", DIGI_AMOEBA, 409, PRI_SECTOROBJ, -200, 200, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("BODY6.VOC", DIGI_BODYFALL2, 410, PRI_PLAYERDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("GIBS01.VOC", DIGI_GIBS3, 411, PRI_LOW_PLAYERWEAP, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("CHOK01.VOC", DIGI_NINJACHOKE, 412, PRI_NPCDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("TRAIN3.VOC", DIGI_TRAIN3, 413, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAINR02.VOC", DIGI_TRAINR02, 414, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TRAIN8.VOC", DIGI_TRAIN8, 415, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TCLID01.VOC", DIGI_TRASHLID, 416, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// player voices +DIGI_ENTRY("ACCU01.VOC", DIGI_GETMEDKIT, 417, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("AHH03.VOC", DIGI_AHH, 418, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// Pachinko +DIGI_ENTRY("PALARM1.VOC", DIGI_PALARM, 419, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PFLIP4.VOC", DIGI_PFLIP, 420, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PROLL1.VOC", DIGI_PROLL1, 421, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PROLL2.VOC", DIGI_PROLL2, 422, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("PROLL3.VOC", DIGI_PROLL3, 423, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// BUNNY +DIGI_ENTRY("RABATK1.VOC", DIGI_BUNNYATTACK, 424, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RABDIE1.VOC", DIGI_BUNNYDIE1, 425, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RABDIE2.VOC", DIGI_BUNNYDIE2, 426, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RABDIE3.VOC", DIGI_BUNNYDIE3, 427, PRI_NPCDEATH, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RABAMB.VOC", DIGI_BUNNYAMBIENT, 428, PRI_NPCAMBIENT, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("STONE2.VOC", DIGI_STONESLIDE, 429, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("NINCUT3.VOC", DIGI_NINJAINHALF, 430, PRI_NPCDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("RIPCHST1.VOC", DIGI_RIPPER2CHEST, 431, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("WHIPIN2.VOC", DIGI_WHIPME, 432, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("ENDLEV3.VOC", DIGI_ENDLEV, 433, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MDALARM1.VOC", DIGI_MDALARM, 434, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("METALBRK.VOC", DIGI_BREAKMETAL, 435, PRI_AMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("DEBRIBRK.VOC", DIGI_BREAKDEBRIS, 436, PRI_AMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MARBELS.VOC", DIGI_BREAKMARBELS, 437, PRI_AMBIENT, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BANZAI1.VOC", DIGI_BANZAI, 438, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HAHA19.VOC", DIGI_HAHA1, 439, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HAHA11.VOC", DIGI_HAHA2, 440, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("HAHA15.VOC", DIGI_HAHA3, 441, PRI_PLAYERDEATH, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TELEPT02.VOC", DIGI_ITEM_SPAWN, 442, PRI_ITEM, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// More Player Voices +DIGI_ENTRY("JG1075.VOC", DIGI_NOREPAIRMAN2, 443, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG1082.VOC", DIGI_NOPOWER, 444, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG1087.VOC", DIGI_DOUBLEUZI, 445, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG1088.VOC", DIGI_NOTORDBUNNY, 446, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG1103.VOC", DIGI_CANBEONLYONE, 447, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2000.VOC", DIGI_MIRROR1, 448, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2005.VOC", DIGI_MIRROR2, 449, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2020.VOC", DIGI_HITTINGWALLS, 450, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2032.VOC", DIGI_GOTRAILGUN, 451, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2053.VOC", DIGI_RABBITHUMP1, 452, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2054.VOC", DIGI_RABBITHUMP2, 453, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2045.VOC", DIGI_RABBITHUMP3, 454, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2087.VOC", DIGI_RABBITHUMP4, 455, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2074.VOC", DIGI_FAGRABBIT1, 456, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2075.VOC", DIGI_FAGRABBIT2, 457, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2078.VOC", DIGI_FAGRABBIT3, 458, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG3005.VOC", DIGI_STINKLIKEBABBOON, 459, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG3017.VOC", DIGI_WHATYOUEATBABY, 460, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG3047.VOC", DIGI_WHATDIEDUPTHERE, 461, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG3022.VOC", DIGI_YOUGOPOOPOO, 462, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG6053.VOC", DIGI_PULLMYFINGER, 463, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG3059.VOC", DIGI_SOAPYOUGOOD, 464, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG4012.VOC", DIGI_WASHWANG, 465, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG3070.VOC", DIGI_DROPSOAP, 466, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG6051.VOC", DIGI_REALTITS, 467, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG4002.VOC", DIGI_MSTRLEEP, 468, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG4024.VOC", DIGI_SEEKLEEPADVICE, 469, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG5042.VOC", DIGI_AVENGELEEPDEATH, 470, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG5049A.VOC", DIGI_LEEPGHOST, 471, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("WDOOR02.VOC", DIGI_DOOR1, 472, PRI_SECTOROBJ, -200, 200, 0, 8000, VF_NORMAL) +DIGI_ENTRY("MDOOR03.VOC", DIGI_DOOR2, 473, PRI_SECTOROBJ, -200, 200, 0, 8000, VF_NORMAL) +DIGI_ENTRY("603981_1.VOC", DIGI_DOOR3, 474, PRI_SECTOROBJ, -200, 200, 0, 8000, VF_NORMAL) +DIGI_ENTRY("FLAG03.VOC", DIGI_FLAGWAVE, 475, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) + +DIGI_ENTRY("JG7009.VOC", DIGI_SURFACE, 476, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG7001.VOC", DIGI_GASHURT, 477, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG2001.VOC", DIGI_BONUS_GRAB, 478, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("ACHCRY04.VOC", DIGI_ANIMECRY, 479, PRI_SECTOROBJ, 0, 0, 0, -8000, VF_LOOP) +DIGI_ENTRY("ACHS010.VOC", DIGI_ANIMESING1, 480, PRI_SECTOROBJ, 0, 0, 0, -8000, VF_NORMAL) +DIGI_ENTRY("ACHT1006.VOC", DIGI_ANIMEMAD1, 481, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ACHS016.VOC", DIGI_ANIMESING2, 482, PRI_SECTOROBJ, 0, 0, 0, -8000, VF_NORMAL) +DIGI_ENTRY("ACHT120A.VOC", DIGI_ANIMEMAD2, 483, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("TELEPT02.VOC", DIGI_PLAYER_TELEPORT, 484, PRI_LOW_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SLASH1.VOC", DIGI_INTRO_SLASH, 485, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("WARNING.VOC", DIGI_WARNING, 486, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("WHIRL1.VOC", DIGI_INTRO_WHIRL, 487, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("ACHF1003.VOC", DIGI_TOILETGIRLFART1, 488, PRI_NPCAMBIENT, -300, 300, 0, -16000, VF_NORMAL) +DIGI_ENTRY("ACHF1002.VOC", DIGI_TOILETGIRLFART2, 489, PRI_NPCAMBIENT, -300, 300, 0, -16000, VF_NORMAL) +DIGI_ENTRY("ACHF1016.VOC", DIGI_TOILETGIRLFART3, 490, PRI_NPCAMBIENT, -300, 300, 0, -16000, VF_NORMAL) + +DIGI_ENTRY("CHIMES4.VOC", DIGI_WINDCHIMES, 491, PRI_SECTOROBJ, 0, 0, 0, -8000, VF_LOOP) + +// Yet more LoWang voices +DIGI_ENTRY("JGB023.VOC", DIGI_MADATCARPET, 492, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB020.VOC", DIGI_JUMPONCARPET, 493, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB080.VOC", DIGI_USEBROKENVEHICLE, 494, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB106.VOC", DIGI_STEPONCALTROPS, 495, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB130.VOC", DIGI_WANGSEESERP, 496, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGSB4.VOC", DIGI_SERPTAUNTWANG, 497, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB166.VOC", DIGI_WANGTAUNTSERP1, 498, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB156.VOC", DIGI_WANGTAUNTSERP2, 499, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB193.VOC", DIGI_WANGORDER1, 500, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB202.VOC", DIGI_WANGORDER2, 501, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JGB340A.VOC", DIGI_WANGDROWNING, 502, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("JGEN06.VOC", DIGI_ZILLAREGARDS, 503, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("MSG9.VOC", DIGI_PMESSAGE, 504, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("UGLY1A.VOC", DIGI_SHAREND_UGLY1, 505, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("UGLY1B.VOC", DIGI_SHAREND_UGLY2, 506, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("TELEPT07.VOC", DIGI_SHAREND_TELEPORT, 507, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("GOROSW1.VOC", DIGI_HOTHEADSWITCH, 508, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BTCREAK2.VOC", DIGI_BOATCREAK, 509, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("BTRUN05.VOC", DIGI_BOATRUN2, 510, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("BTIDLE4.VOC", DIGI_BOATIDLE, 511, PRI_SECTOROBJ, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("SHIPBELL.VOC", DIGI_SHIPBELL, 512, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("SHIPHRN1.VOC", DIGI_FOGHORN, 513, PRI_AMBIENT, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("EXP3.VOC", DIGI_CANNON, 514, PRI_HI_PLAYERWEAP, 0, 0, 0, DIST_WIDE, VF_NORMAL) + +// Yet even more player voices! +DIGI_ENTRY("JG41001.VOC", DIGI_JG41001, 515, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41012.VOC", DIGI_JG41012, 516, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41018.VOC", DIGI_JG41018, 517, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41028.VOC", DIGI_JG41028, 518, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41048.VOC", DIGI_JG41048, 519, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41052.VOC", DIGI_JG41052, 520, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41058.VOC", DIGI_JG41058, 521, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41060.VOC", DIGI_JG41060, 522, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG41075.VOC", DIGI_JG41075, 523, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42004.VOC", DIGI_JG42004, 524, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42019.VOC", DIGI_JG42019, 525, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42021.VOC", DIGI_JG42021, 526, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42028.VOC", DIGI_JG42028, 527, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42033.VOC", DIGI_JG42033, 528, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42034.VOC", DIGI_JG42034, 529, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42050.VOC", DIGI_JG42050, 530, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42056.VOC", DIGI_JG42056, 531, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG42061.VOC", DIGI_JG42061, 532, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG43004.VOC", DIGI_JG43004, 533, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG43015.VOC", DIGI_JG43015, 534, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG43019.VOC", DIGI_JG43019, 535, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG43021.VOC", DIGI_JG43021, 536, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44011.VOC", DIGI_JG44011, 537, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44014.VOC", DIGI_JG44014, 538, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44027.VOC", DIGI_JG44027, 539, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44038.VOC", DIGI_JG44038, 540, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44039.VOC", DIGI_JG44039, 541, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44048.VOC", DIGI_JG44048, 542, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44052.VOC", DIGI_JG44052, 543, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45014.VOC", DIGI_JG45014, 544, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG44068.VOC", DIGI_JG44068, 545, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45010.VOC", DIGI_JG45010, 546, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45018.VOC", DIGI_JG45018, 547, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45030.VOC", DIGI_JG45030, 548, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45033.VOC", DIGI_JG45033, 549, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45043.VOC", DIGI_JG45043, 550, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45053.VOC", DIGI_JG45053, 551, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG45067.VOC", DIGI_JG45067, 552, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG46005.VOC", DIGI_JG46005, 553, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG46010.VOC", DIGI_JG46010, 554, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +// And the girls talk back to Wang +// Car Girl +DIGI_ENTRY("LANI049.VOC", DIGI_LANI049, 555, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI051.VOC", DIGI_LANI051, 556, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI052.VOC", DIGI_LANI052, 557, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI054.VOC", DIGI_LANI054, 558, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) + +// Sailor Moon +DIGI_ENTRY("LANI060.VOC", DIGI_LANI060, 559, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI063.VOC", DIGI_LANI063, 560, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI065.VOC", DIGI_LANI065, 561, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI066.VOC", DIGI_LANI066, 562, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) + +// Mechanic +DIGI_ENTRY("LANI073.VOC", DIGI_LANI073, 563, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI075.VOC", DIGI_LANI075, 564, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI077.VOC", DIGI_LANI077, 565, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI079.VOC", DIGI_LANI079, 566, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) + +// Prune +DIGI_ENTRY("LANI089.VOC", DIGI_LANI089, 567, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI091.VOC", DIGI_LANI091, 568, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI093.VOC", DIGI_LANI093, 569, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("LANI095.VOC", DIGI_LANI095, 570, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) + +DIGI_ENTRY("AD5.VOC", DIGI_VENTWALK, 571, PRI_ENVIRONMENT, -300, 300, 0, 8000, VF_NORMAL) +DIGI_ENTRY("AD6.VOC", DIGI_CARWALK, 572, PRI_ENVIRONMENT, -300, 300, 0, 8000, VF_NORMAL) +DIGI_ENTRY("JET05.VOC", DIGI_JETSOAR, 573, PRI_SECTOROBJ, -100, 100, 0, 8000, VF_NORMAL) +DIGI_ENTRY("VC04.VOC", DIGI_VACUUM, 574, PRI_SECTOROBJ, -100, 100, 0, DIST_NORMAL, VF_LOOP) + +// GIRL NINJA +DIGI_ENTRY("LANI017.VOC", DIGI_GIRLNINJAALERTT, 575, PRI_NPCATTACK, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LANI033.VOC", DIGI_GIRLNINJASCREAM, 576, PRI_NPCDEATH, -200, 200, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("LANI001.VOC", DIGI_GIRLNINJAALERT, 577, PRI_NPCATTACK, -200, 200, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("CACKLE.VOC", DIGI_PRUNECACKLE, 578, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("CACKLE2.VOC", DIGI_PRUNECACKLE2, 579, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) +DIGI_ENTRY("CACKLE3.VOC", DIGI_PRUNECACKLE3, 580, PRI_NPCAMBIENT, -200, 200, 0, -16000, VF_NORMAL) + +DIGI_ENTRY("SUMO058.VOC", DIGI_SUMOSTOMP, 581, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ELEV01.VOC", DIGI_VATOR, 582, PRI_SECTOROBJ, -100, 100, 0, DIST_NORMAL, VF_NORMAL) + +DIGI_ENTRY("JG9009.VOC", DIGI_JG9009, 583, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z16004.VOC", DIGI_Z16004, 584, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z16012.VOC", DIGI_Z16012, 585, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z16022.VOC", DIGI_Z16022, 586, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z16027.VOC", DIGI_Z16027, 587, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG93030.VOC", DIGI_JG93030, 588, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG94002.VOC", DIGI_JG94002, 589, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z17010.VOC", DIGI_Z17010, 590, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z17052.VOC", DIGI_Z17052, 591, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z17025.VOC", DIGI_Z17025, 592, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ML25014.VOC", DIGI_ML25014, 593, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ML250101.VOC",DIGI_ML250101, 594, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG9022.VOC", DIGI_JG9022, 595, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG9032.VOC", DIGI_JG9032, 596, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG9038.VOC", DIGI_JG9038, 597, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG9055.VOC", DIGI_JG9055, 598, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG9060.VOC", DIGI_JG9060, 599, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG92055.VOC", DIGI_JG92055, 600, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ML25032.VOC", DIGI_ML25032, 601, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG92036.VOC", DIGI_JG92036, 602, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG92042.VOC", DIGI_JG92042, 603, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ML26001.VOC", DIGI_ML26001, 604, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG93000.VOC", DIGI_JG93000, 605, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG93011.VOC", DIGI_JG93011, 606, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG93018.VOC", DIGI_JG93018, 607, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG93023.VOC", DIGI_JG93023, 608, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ML26008.VOC", DIGI_ML26008, 609, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ML26011.VOC", DIGI_ML26011, 610, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG94007.VOC", DIGI_JG94007, 611, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG94024.VOC", DIGI_JG94024, 612, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG94039.VOC", DIGI_JG94039, 613, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("JG95012.VOC", DIGI_JG95012, 614, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZWALK5.VOC", DIGI_ZILLASTOMP, 615, PRI_NPCATTACK, -100, 100, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC1.VOC", DIGI_ZC1, 616, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC2.VOC", DIGI_ZC2, 617, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC3.VOC", DIGI_ZC3, 618, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC4.VOC", DIGI_ZC4, 619, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC5.VOC", DIGI_ZC5, 620, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC6.VOC", DIGI_ZC6, 621, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC7.VOC", DIGI_ZC7, 622, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_LOOP) +DIGI_ENTRY("ZC8.VOC", DIGI_ZC8, 623, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("ZC9.VOC", DIGI_ZC9, 624, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) +DIGI_ENTRY("Z16043.VOC", DIGI_Z16043, 625, PRI_PLAYERVOICE, 0, 0, 0, DIST_NORMAL, VF_NORMAL) + +#undef DIGI_ENTRY diff --git a/polymer/eduke32/source/sw/src/draw.c b/polymer/eduke32/source/sw/src/draw.c new file mode 100644 index 000000000..023bbe5c3 --- /dev/null +++ b/polymer/eduke32/source/sw/src/draw.c @@ -0,0 +1,2724 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#define QUIET +#include "build.h" +#include "pragmas.h" +#include "cache1d.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "quake.h" +#include "vis.h" + +#include "jsector.h" + +#include "mytypes.h" +#include "control.h" +#include "function.h" +#include "net.h" +#include "pal.h" +#include "player.h" +#include "jtags.h" +#include "parent.h" + +#include "cache.h" +#include "reserve.h" + +#include "text.h" +#include "menus.h" +#include "interp.h" +#include "sector.h" + +static int OverlapDraw = FALSE; +extern BOOL QuitFlag, LocationInfo, ConPanel, SpriteInfo, PauseKeySet; +extern BOOL Voxel; +extern char tempbuf[]; +extern char buffer[]; +BOOL DrawScreen; +extern short f_c; + +extern BOOL HelpInputMode; +extern short HelpPage; +extern short HelpPagePic[]; +extern ParentalStruct aVoxelArray[MAXTILES]; +extern BOOL RedrawScreen; +BOOL RedrawCompass=FALSE; +extern int Follow_posx,Follow_posy; + +int ConnectCopySprite(SPRITEp tsp); +void PreDrawStackedWater(void); +VOID DrawCompass(PLAYERp pp); + +#if 1 +VOID +ShadeSprite(SPRITEp tsp) +{ + // set shade of sprite + tsp->shade = sector[tsp->sectnum].floorshade - 25; + + if (tsp->shade > -3) + tsp->shade = -3; + + if (tsp->shade < -30) + tsp->shade = -30; +} +#else +#endif + + +short +GetRotation(short tSpriteNum, int viewx, int viewy) +{ + static short RotTable8[] = {0, 7, 6, 5, 4, 3, 2, 1}; + static short RotTable5[] = {0, 1, 2, 3, 4, 3, 2, 1}; + short rotation; + extern short screenpeek; + + SPRITEp tsp = &tsprite[tSpriteNum]; + USERp tu = User[tsp->owner]; + PLAYERp pp = Player + screenpeek; + short angle2; + + if (tu->RotNum == 0) + return 0; + + // Get which of the 8 angles of the sprite to draw (0-7) + // rotation ranges from 0-7 + angle2 = getangle(tsp->x - viewx, tsp->y - viewy); + rotation = ((tsp->ang + 3072 + 128 - angle2) & 2047); + rotation = (rotation >> 8) & 7; + + if (tu->RotNum == 5) + { + if (TEST(tu->Flags, SPR_XFLIP_TOGGLE)) + { + if (rotation <= 4) + { + // leave rotation alone + RESET(tsp->cstat, CSTAT_SPRITE_XFLIP); + } + else + { + rotation = (8 - rotation); + SET(tsp->cstat, CSTAT_SPRITE_XFLIP); // clear x-flipping bit + } + } + else + { + if (rotation > 3 || rotation == 0) + { + // leave rotation alone + RESET(tsp->cstat, CSTAT_SPRITE_XFLIP); // clear x-flipping bit + } + else + { + rotation = (8 - rotation); + SET(tsp->cstat, CSTAT_SPRITE_XFLIP); // set + } + } + + // Special case bunk + if (tu->ID == TOILETGIRL_R0 || tu->ID == WASHGIRL_R0 || tu->ID == TRASHCAN || + tu->ID == CARGIRL_R0 || tu->ID == MECHANICGIRL_R0 || tu->ID == PRUNEGIRL_R0 || + tu->ID == SAILORGIRL_R0) + RESET(tsp->cstat, CSTAT_SPRITE_XFLIP); // clear x-flipping bit + + return RotTable5[rotation]; + } + + return RotTable8[rotation]; + +} + +/* + + +!AIC - At draw time this is called for actor rotation. GetRotation() is more +complex than needs to be in part because importing of actor rotations and x-flip +directions was not standardized. + +*/ + +int +SetActorRotation(short tSpriteNum, int viewx, int viewy) +{ + SPRITEp tsp = &tsprite[tSpriteNum]; + USERp tu = User[tsp->owner]; + short StateOffset, Rotation; + + // don't modify ANY tu vars - back them up! + STATEp State = tu->State; + STATEp StateStart = tu->StateStart; + + if (tu->RotNum == 0) + return 0; + + // Get the offset into the State animation + StateOffset = State - StateStart; + + // Get the rotation angle + Rotation = GetRotation(tSpriteNum, viewx, viewy); + + ASSERT(Rotation < 5); + + // Reset the State animation start based on the Rotation + StateStart = tu->Rot[Rotation]; + + // Set the sprites state + State = StateStart + StateOffset; + + // set the picnum here - may be redundant, but we just changed states and + // thats a big deal + tsp->picnum = State->Pic; + + //sprintf(ds,"SetActorRotation:tsp->picnum: %d",tsp->picnum); + //CON_Message(ds); + + /* + + !AIC KEY - For actor states EVERY rotation needs to have the same tics + animators. The only thing different can be the picnum. If not then sync bugs + will occur. This code attempts to check to the best of its ability for this + problem. Should go away with shipped compile. + + */ + +#if DEBUG + { + short i; + + for (i = 0; i < tu->RotNum; i++) + { + STATEp TestStateStart, TestState; + + TestStateStart = tu->Rot[i]; + TestState = TestStateStart + StateOffset; + + ASSERT(State->Tics == TestState->Tics); + ASSERT(State->Animator == TestState->Animator); + } + } +#endif + return 0; +} + +int +DoShadowFindGroundPoint(SPRITEp sp) +{ + // USES TSPRITE !!!!! + USERp u = User[sp->owner]; + SPRITEp hsp; + int ceilhit, florhit; + int hiz, loz = u->loz; + short save_cstat, bak_cstat; + BOOL found = FALSE; + + // recursive routine to find the ground - either sector or floor sprite + // skips over enemy and other types of sprites + + // IMPORTANT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // This will return invalid FAF ceiling and floor heights inside of analyzesprite + // because the ceiling and floors get moved out of the way for drawing. + + save_cstat = sp->cstat; + RESET(sp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN); + FAFgetzrangepoint(sp->x, sp->y, sp->z, sp->sectnum, &hiz, &ceilhit, &loz, &florhit); + sp->cstat = save_cstat; + + ASSERT(TEST(florhit, HIT_SPRITE | HIT_SECTOR)); + + switch (TEST(florhit, HIT_MASK)) + { + case HIT_SPRITE: + { + hsp = &sprite[NORM_SPRITE(florhit)]; + + if (TEST(hsp->cstat, CSTAT_SPRITE_FLOOR)) + { + // found a sprite floor + return loz; + } + else + { + // reset the blocking bit of what you hit and try again - + // recursive + bak_cstat = hsp->cstat; + RESET(hsp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN); + loz = DoShadowFindGroundPoint(sp); + hsp->cstat = bak_cstat; + } + } + + case HIT_SECTOR: + { + return loz; + } + + default: + ASSERT(TRUE == FALSE); + break; + } + + return loz; + +} + +#if 0 +#define GENERIC_SHADOW_PIC 66 +extern BOOL bVoxelsOn; +VOID +DoVoxelShadow(SPRITEp tspr) +{ + // Check for voxels + if (bVoxelsOn) + { + switch (tspr->picnum) + { + case ICON_STAR: // 1793 + case ICON_UZI: // 1797 + case ICON_UZIFLOOR: // 1807 + case ICON_LG_UZI_AMMO: // 1799 + case ICON_HEART: // 1824 + case ICON_HEART_LG_AMMO: // 1820 + case ICON_GUARD_HEAD: // 1814 + case ICON_FIREBALL_LG_AMMO: // 3035 + case ICON_ROCKET: // 1843 + case ICON_SHOTGUN: // 1794 + case ICON_LG_ROCKET: // 1796 + case ICON_LG_SHOTSHELL: // 1823 + case ICON_MICRO_GUN: // 1818 + case ICON_MICRO_BATTERY: // 1800 + case ICON_GRENADE_LAUNCHER: // 1817 + case ICON_LG_GRENADE: // 1831 + case ICON_LG_MINE: // 1842 + case ICON_RAIL_GUN: // 1811 + case ICON_RAIL_AMMO: // 1812 + case ICON_SM_MEDKIT: // 1802 + case ICON_MEDKIT: // 1803 + case ICON_CHEMBOMB: // 1808 + case ICON_FLASHBOMB: // 1805 + case ICON_NUKE: // 1809 + case ICON_CALTROPS: + case ICON_BOOSTER: // 1810 + case ICON_HEAT_CARD: // 1819 + case ICON_REPAIR_KIT: // 1813 + case ICON_EXPLOSIVE_BOX: // 1801 + case ICON_ENVIRON_SUIT: // 1837 + case ICON_FLY: // 1782 + case ICON_CLOAK: // 1826 + case ICON_NIGHT_VISION: // 3031 + case ICON_NAPALM: // 3046 + case ICON_RING: // 3050 + //case ICON_GOROAMMO: // 3035 + //case ICON_HEARTAMMO: // 1820 + case ICON_RINGAMMO: // 3054 + case ICON_NAPALMAMMO: // 3058 + case ICON_GRENADE: // 3059 + //case ICON_OXYGEN: // 1800 + case ICON_ARMOR: // 3030 + case BLUE_KEY: // 1766 + case RED_KEY: // 1770 + case GREEN_KEY: // 1774 + case YELLOW_KEY: // 1778 + case GOLD_SKELKEY: + case SILVER_SKELKEY: + case BRONZE_SKELKEY: + case RED_SKELKEY: + case BLUE_CARD: + case RED_CARD: + case GREEN_CARD: + case YELLOW_CARD: +// tspr->picnum = GENERIC_SHADOW_PIC; + tspr->xrepeat = 0; // For now, don't do voxel shadows + tspr->yrepeat = 0; +// tspr->xrepeat = 27; +// tspr->yrepeat = 4; + //tspr->z+=(sintable[(rotang*2)%2047]/16); + break; + } + } +} +#endif + +VOID +DoShadows(SPRITEp tsp, int viewz) +{ + SPRITEp new = &tsprite[spritesortcnt]; + USERp tu = User[tsp->owner]; + int ground_dist = 0; + int view_dist = 0; + int loz; + short xrepeat; + short yrepeat; + short sectnum; + + sectnum = tsp->sectnum; + // make sure its the correct sector + // DoShadowFindGroundPoint calls FAFgetzrangepoint and this is sensitive + //updatesectorz(tsp->x, tsp->y, tsp->z, §num); + updatesector(tsp->x, tsp->y, §num); + + if (sectnum < 0) + { + //int cz,fz; + //getzsofslope(tsp->sectnum, tsp->x, tsp->y, &cz, &fz); + ////DSPRINTF(ds,"Shad sect !fnd x%d, y%d, z%d, sect%d, cz %d, fz %d", tsp->x, tsp->y, tsp->z, tsp->sectnum, cz, fz); + //MONO_PRINT(ds); + return; + } + + tsp->sectnum = sectnum; + memcpy(new, tsp, sizeof(SPRITE)); + // shadow is ALWAYS draw last - status is priority + new->statnum = MAXSTATUS; + new->sectnum = sectnum; + + if ((tsp->yrepeat >> 2) > 4) + { + yrepeat = (tsp->yrepeat >> 2) - (SPRITEp_SIZE_Y(tsp) / 64) * 2; + xrepeat = new->xrepeat; + } + else + { + yrepeat = new->yrepeat; + xrepeat = new->xrepeat; + } + + new->shade = 127; + SET(new->cstat, CSTAT_SPRITE_TRANSLUCENT); + + loz = tu->loz; + if (tu->lo_sp) + { + if (!TEST(tu->lo_sp->cstat, CSTAT_SPRITE_WALL | CSTAT_SPRITE_FLOOR)) + { + loz = DoShadowFindGroundPoint(tsp); + } + } + +#if 0 + if (SectUser[tsp->sectnum] && SectUser[tsp->sectnum]->depth) + { + loz -= Z(SectUser[tsp->sectnum]->depth); + } +#endif + + // need to find the ground here + new->z = loz; + + // if below or close to sprites z don't bother to draw it + if ((viewz - loz) > -Z(8)) + return; + + // if close to shadows z shrink it + view_dist = labs(loz - viewz) >> 8; + if (view_dist < 32) + view_dist = 256/view_dist; + else + view_dist = 0; + + // make shadow smaller depending on height from ground + ground_dist = labs(loz - SPRITEp_BOS(tsp)) >> 8; + ground_dist = DIV16(ground_dist); + + xrepeat = max(xrepeat - ground_dist - view_dist, 4); + yrepeat = max(yrepeat - ground_dist - view_dist, 4); + xrepeat = min(xrepeat, 255); + yrepeat = min(yrepeat, 255); + + new->xrepeat = xrepeat; + new->yrepeat = yrepeat; + + // Check for voxel items and use a round generic pic if so + //DoVoxelShadow(new); + + spritesortcnt++; +} + +VOID +DoMotionBlur(SPRITEp tsp) +{ + SPRITEp new; + USERp tu = User[tsp->owner]; + int nx,ny,nz = 0,dx,dy,dz; + short i, ang; + short xrepeat, yrepeat, repeat_adj = 0; + int z_amt_per_pixel; + + ang = NORM_ANGLE(tsp->ang + 1024); + + if (tsp->xvel == 0) + { + return; + } + + if (TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY)) + { + z_amt_per_pixel = (((int)-tu->jump_speed * ACTORMOVETICS)<<16)/tsp->xvel; + } + else + { + z_amt_per_pixel = (((int)-tsp->zvel)<<16)/tsp->xvel; + } + + switch (tu->motion_blur_dist) + { + case 64: + dx = nx = MOVEx(64, ang); + dy = ny = MOVEy(64, ang); + nz = (z_amt_per_pixel * 64)>>16; + break; + case 128: + dx = nx = MOVEx(128, ang); + dy = ny = MOVEy(128, ang); + nz = (z_amt_per_pixel * 128)>>16; + break; + case 256: + dx = nx = MOVEx(256, ang); + dy = ny = MOVEy(256, ang); + nz = (z_amt_per_pixel * 256)>>16; + break; + case 512: + dx = nx = MOVEx(512, ang); + dy = ny = MOVEy(512, ang); + nz = (z_amt_per_pixel * 512)>>16; + break; + default: + dx = nx = MOVEx(tu->motion_blur_dist, ang); + dy = ny = MOVEy(tu->motion_blur_dist, ang); + break; + } + + dz = nz; + + xrepeat = tsp->xrepeat; + yrepeat = tsp->yrepeat; + + switch (TEST(tu->Flags2, SPR2_BLUR_TAPER)) + { + case 0: + repeat_adj = 0; + break; + case SPR2_BLUR_TAPER_SLOW: + repeat_adj = xrepeat / (tu->motion_blur_num*2); + break; + case SPR2_BLUR_TAPER_FAST: + repeat_adj = xrepeat / tu->motion_blur_num; + break; + } + + for (i = 0; i < tu->motion_blur_num; i++) + { + new = &tsprite[spritesortcnt]; + memcpy(new, tsp, sizeof(SPRITE)); + SET(new->cstat, CSTAT_SPRITE_TRANSLUCENT|CSTAT_SPRITE_TRANS_FLIP); + + new->x += dx; + new->y += dy; + dx += nx; + dy += ny; + + new->z += dz; + dz += nz; + + new->xrepeat = xrepeat; + new->yrepeat = yrepeat; + + xrepeat -= repeat_adj; + yrepeat -= repeat_adj; + + spritesortcnt++; + } + +} + +VOID SetVoxelSprite(SPRITEp sp, short pic) +{ + SET(sp->cstat, CSTAT_SPRITE_SLAB); + sp->picnum = pic; +} + +VOID WarpCopySprite(VOID) +{ + SPRITEp new, sp1, sp2, sp; + short sn, nsn; + short sn2, nsn2; + short spnum, next_spnum; + int xoff,yoff,zoff; + short match; + short sect1, sect2; + + // look for the first one + TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP_COPY_SPRITE1], sn, nsn) + { + sp1 = &sprite[sn]; + match = sp1->lotag; + + // look for the second one + TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP_COPY_SPRITE2], sn2, nsn2) + { + sp = &sprite[sn2]; + + if (sp->lotag == match) + { + sp2 = sp; + sect1 = sp1->sectnum; + sect2 = sp2->sectnum; + + TRAVERSE_SPRITE_SECT(headspritesect[sect1], spnum, next_spnum) + { + if (&sprite[spnum] == sp1) + continue; + + if (sprite[spnum].picnum == ST1) + continue; + + new = &tsprite[spritesortcnt]; + memcpy(new, &sprite[spnum], sizeof(SPRITE)); + spritesortcnt++; + new->owner = spnum; + new->statnum = 0; + + xoff = sp1->x - new->x; + yoff = sp1->y - new->y; + zoff = sp1->z - new->z; + + new->x = sp2->x - xoff; + new->y = sp2->y - yoff; + new->z = sp2->z - zoff; + new->sectnum = sp2->sectnum; + } + + TRAVERSE_SPRITE_SECT(headspritesect[sect2], spnum, next_spnum) + { + if (&sprite[spnum] == sp2) + continue; + + if (sprite[spnum].picnum == ST1) + continue; + + new = &tsprite[spritesortcnt]; + memcpy(new, &sprite[spnum], sizeof(SPRITE)); + spritesortcnt++; + new->owner = spnum; + new->statnum = 0; + + xoff = sp2->x - new->x; + yoff = sp2->y - new->y; + zoff = sp2->z - new->z; + + new->x = sp1->x - xoff; + new->y = sp1->y - yoff; + new->z = sp1->z - zoff; + new->sectnum = sp1->sectnum; + } + } + } + } +} + +VOID DoStarView(SPRITEp tsp, USERp tu, int viewz) +{ + extern STATE s_Star[], s_StarDown[]; + extern STATE s_StarStuck[], s_StarDownStuck[]; + int zdiff = viewz - tsp->z; + + if (labs(zdiff) > Z(24)) + { + if (tu->StateStart == s_StarStuck) + tsp->picnum = s_StarDownStuck[tu->State - s_StarStuck].Pic; + else + tsp->picnum = s_StarDown[tu->State - s_Star].Pic; + + if (zdiff > 0) + SET(tsp->cstat, CSTAT_SPRITE_YFLIP); + } + else + { + if (zdiff > 0) + SET(tsp->cstat, CSTAT_SPRITE_YFLIP); + } +} + +VOID +analyzesprites(int viewx, int viewy, int viewz, BOOL mirror) +{ + int tSpriteNum, j, k; + short SpriteNum, pnum; + int smr4, smr2; + SPRITEp tsp; + USERp tu; + static int ang = 0; + PLAYERp pp = Player + screenpeek; + short newshade=0; + + + ang = NORM_ANGLE(ang + 12); + + smr4 = smoothratio + (((int) MoveSkip4) << 16); + smr2 = smoothratio + (((int) MoveSkip2) << 16); + + for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--) + { + SpriteNum = tsprite[tSpriteNum].owner; + tsp = &tsprite[tSpriteNum]; + tu = User[SpriteNum]; + + //if(tsp->statnum == STAT_GENERIC_QUEUE) + // CON_ConMessage("tsp->pal = %d",tsp->pal); + +#if 0 + // Brighten up the sprite if set somewhere else to do so + if (tu && tu->Vis > 0) + { + short tmpshade; // Having this prevent overflow + + tmpshade = tsp->shade - tu->Vis; + if (tmpshade < -128) tmpshade = -128; + + tsp->shade = tmpshade; + tu->Vis -= 8; + } +#endif + + // don't draw these + if (tsp->statnum >= STAT_DONT_DRAW) + { + tsp->owner = -1; + continue; + } + + // Diss any parentally locked sprites + if (gs.ParentalLock || Global_PLock) + { + if (aVoxelArray[tsp->picnum].Parental == 6145) + { + tsp->owner = -1; + tu = NULL; + } + else if (aVoxelArray[tsp->picnum].Parental > 0) + { + ASSERT(aVoxelArray[tsp->picnum].Parental >= 0 && aVoxelArray[tsp->picnum].Parental < 6145); + tsp->picnum=aVoxelArray[tsp->picnum].Parental; // Change the pic + } + } + + if (tu) + { + if (tsp->statnum != STAT_DEFAULT) + { + if (TEST(tu->Flags, SPR_SKIP4)) + { + if (tsp->statnum <= STAT_SKIP4_INTERP_END) + { + tsp->x = tu->ox + mulscale(tsp->x - tu->ox, smr4, 18); + tsp->y = tu->oy + mulscale(tsp->y - tu->oy, smr4, 18); + tsp->z = tu->oz + mulscale(tsp->z - tu->oz, smr4, 18); + } + } + + if (TEST(tu->Flags, SPR_SKIP2)) + { + if (tsp->statnum <= STAT_SKIP2_INTERP_END) + { + tsp->x = tu->ox + mulscale(tsp->x - tu->ox, smr2, 17); + tsp->y = tu->oy + mulscale(tsp->y - tu->oy, smr2, 17); + tsp->z = tu->oz + mulscale(tsp->z - tu->oz, smr2, 17); + } + } + } + + if (gs.Shadows && TEST(tu->Flags, SPR_SHADOW)) + { + DoShadows(tsp, viewz); + } + + //#define UK_VERSION 1 + + //#define DART_REPEAT 6 + //#define DART_PIC 2233 + if (useDarts) + if (tu->ID == 1793 || tsp->picnum == 1793) + { + tsp->picnum = 2519; + tsp->xrepeat = 27; + tsp->yrepeat = 29; + } + +#define DART_PIC 2526 +#define DART_REPEAT 16 + if (tu->ID == STAR1) + { + if (useDarts) + { + tsp->picnum = DART_PIC; + tsp->ang = NORM_ANGLE(tsp->ang - 512 - 24); + tsp->xrepeat = tsp->yrepeat = DART_REPEAT; + SET(tsp->cstat, CSTAT_SPRITE_WALL); + } + else + DoStarView(tsp, tu, viewz); + } + + // rotation + if (tu->RotNum > 0) + SetActorRotation(tSpriteNum, viewx, viewy); + + if (tu->motion_blur_num) + { + DoMotionBlur(tsp); + } + + // set palette lookup correctly + if (tsp->pal != sector[tsp->sectnum].floorpal) + { + if (sector[tsp->sectnum].floorpal == PALETTE_DEFAULT) + { + // default pal for sprite is stored in tu->spal + // mostly for players and other monster types + tsp->pal = tu->spal; + } + else + { + // if sector pal is something other than default + SECT_USERp sectu = SectUser[tsp->sectnum]; + BYTE pal = sector[tsp->sectnum].floorpal; + BOOL nosectpal=FALSE; + + // sprite does not take on the new pal if sector flag is set + if (sectu && TEST(sectu->flags, SECTFU_DONT_COPY_PALETTE)) + { + pal = PALETTE_DEFAULT; + nosectpal = TRUE; + } + + //if(tu->spal == PALETTE_DEFAULT) + if (tsp->hitag != SECTFU_DONT_COPY_PALETTE && tsp->hitag != LUMINOUS + && !nosectpal + && pal != PALETTE_FOG && pal != PALETTE_DIVE && + pal != PALETTE_DIVE_LAVA) + tsp->pal = pal; + else + tsp->pal = tu->spal; + + } + } + + // Sprite debug information mode + if (tsp->hitag == 9997) + { + tsp->pal = PALETTE_RED_LIGHTING; + // Turn it off, it gets reset by PrintSpriteInfo + sprite[tu->SpriteNum].hitag = 0; + } + } + + if (useDarts) + if (tsp->statnum == STAT_STAR_QUEUE) + { + tsp->picnum = DART_PIC; + tsp->ang = NORM_ANGLE(tsp->ang - 512); + tsp->xrepeat = tsp->yrepeat = DART_REPEAT; + SET(tsp->cstat, CSTAT_SPRITE_WALL); + } + + // Call my sprite handler + // Does autosizing and voxel handling + JAnalyzeSprites(tsp); + + // only do this of you are a player sprite + //if (tsp->statnum >= STAT_PLAYER0 && tsp->statnum < STAT_PLAYER0 + MAX_SW_PLAYERS) + if (tu && tu->PlayerP) + { + // Shadow spell + if (!TEST(tsp->cstat, CSTAT_SPRITE_TRANSLUCENT)) + ShadeSprite(tsp); + + // sw if its your playersprite + //if ((Player + screenpeek)->PlayerSprite == SpriteNum) + if ((Player + screenpeek)->PlayerSprite == tu->SpriteNum) + { + PLAYERp pp = Player + screenpeek; + if (mirror || TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE|PF_VIEW_FROM_CAMERA)) + { + if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) + SET(tsp->cstat, CSTAT_SPRITE_TRANSLUCENT); + + if (TEST(pp->Flags, PF_CLIMBING)) + { + // move sprite forward some so he looks like he's + // climbing + tsp->x = pp->six + MOVEx(128 + 80, tsp->ang); + tsp->y = pp->siy + MOVEy(128 + 80, tsp->ang); + } + else + { + tsp->x = pp->six; + tsp->y = pp->siy; + } + + tsp->z = tsp->z + pp->siz; + tsp->ang = pp->siang; + //continue; + } + else + { + // dont draw your sprite + tsp->owner = -1; + //SET(tsp->cstat, CSTAT_SPRITE_INVISIBLE); + } + } + } + + if (OverlapDraw && FAF_ConnectArea(tsp->sectnum) && tsp->owner >= 0) + { + ConnectCopySprite(tsp); + } + + // + // kens original sprite shade code he moved out of the engine + // + + switch (tsp->statnum) + { + case STAT_ENEMY: + case STAT_DEAD_ACTOR: + case STAT_FAF_COPY: + break; + default: + newshade = tsp->shade; + newshade += 6; + if (newshade > 127) newshade = 127; + tsp->shade = newshade; + } + + if (TEST(sector[tsp->sectnum].ceilingstat, CEILING_STAT_PLAX)) + { + newshade = tsp->shade; + newshade += sector[tsp->sectnum].ceilingshade; + if (newshade > 127) newshade = 127; + if (newshade < -128) newshade = -128; + tsp->shade = newshade; + } + else + { + newshade = tsp->shade; + newshade += sector[tsp->sectnum].floorshade; + if (newshade > 127) newshade = 127; + if (newshade < -128) newshade = -128; + tsp->shade = newshade; + } + + if (tsp->hitag == 9998) + tsp->shade = 127; // Invisible enemy ninjas + + // Correct shades for luminous sprites + if (tsp->hitag == LUMINOUS) + { + tsp->shade = -128; + } + + if (pp->NightVision && TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY)) + { + if (tu && tu->ID == TRASHCAN) continue; // Don't light up trashcan + + tsp->pal = PALETTE_ILLUMINATE; // Make sprites REALLY bright green. + tsp->shade = -128; + } + + if (tu && tu->PlayerP) + { + if (TEST(tu->Flags2, SPR2_VIS_SHADING)) + { + if ((Player + screenpeek)->PlayerSprite != tu->SpriteNum) + { + if (!TEST(tu->PlayerP->Flags, PF_VIEW_FROM_OUTSIDE)) + { + RESET(tsp->cstat, CSTAT_SPRITE_TRANSLUCENT); + } + } + + tsp->shade = 12 - STD_RANDOM_RANGE(30); + } + } + } + + WarpCopySprite(); + +} + +#if 1 +SPRITEp +get_tsprite(short SpriteNum) +{ + int tSpriteNum; + + for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--) + { + if (tsprite[tSpriteNum].owner == SpriteNum) + return &tsprite[tSpriteNum]; + } + + return NULL; +} + +VOID +post_analyzesprites(void) +{ + int tSpriteNum; + short SpriteNum; + SPRITEp tsp; + USERp tu; + + for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--) + { + SpriteNum = tsprite[tSpriteNum].owner; + if (SpriteNum < 0) continue; // JBF: verify this is safe + tsp = &tsprite[tSpriteNum]; + tu = User[SpriteNum]; + + if (tu) + { + if (tu->ID == FIREBALL_FLAMES && tu->Attach >= 0) + { + //SPRITEp atsp = &sprite[tu->Attach]; + SPRITEp atsp; + + atsp = get_tsprite(tu->Attach); + + if (!atsp) + { + //DSPRINTF(ds,"Attach not found"); + MONO_PRINT(ds); + continue; + } + + tsp->x = atsp->x; + tsp->y = atsp->y; + // statnum is priority - draw this ALWAYS first at 0 + // statnum is priority - draw this ALWAYS last at MAXSTATUS + if (TEST(atsp->extra, SPRX_BURNABLE)) + { + atsp->statnum = 1; + tsp->statnum = 0; + } + else + tsp->statnum = MAXSTATUS; + } + } + } +} +#endif + +VOID +ResizeView(PLAYERp pp) +{ + if (MenuInputMode || InputMode || HelpInputMode || ConPanel || ConInputMode || PauseKeySet) + return; + + if (dimensionmode == 2 || dimensionmode == 5 || dimensionmode == 6) + { + if (PKEY_PRESSED(KEYSC_DASH)||PKEY_PRESSED(KEYSC_GMINUS)) + { + if ((zoom -= (zoom >> 4)) < 48) zoom = 48; + } + + if (PKEY_PRESSED(KEYSC_EQUAL)||PKEY_PRESSED(KEYSC_GPLUS)) + { + if ((zoom += (zoom >> 4)) > 4096) zoom = 4096; + } + + if (KEY_PRESSED(KEYSC_ESC)) + { + extern BOOL ScrollMode2D; + + KEY_PRESSED(KEYSC_ESC) = 0; + dimensionmode = 3; + ScrollMode2D = FALSE; + SetRedrawScreen(pp); + } + } + else + { + if (BUTTON(gamefunc_Shrink_Screen)) // && + // !BUTTONHELD(gamefunc_SizeVi + // ewDown)) + { + CONTROL_ClearButton(gamefunc_Shrink_Screen); + SetBorder(pp, gs.BorderNum + 1); + SetRedrawScreen(pp); + } + + if (BUTTON(gamefunc_Enlarge_Screen)) // && + // !BUTTONHELD(gamefunc_SizeViewUp)) + { + CONTROL_ClearButton(gamefunc_Enlarge_Screen); + SetBorder(pp, gs.BorderNum - 1); + SetRedrawScreen(pp); + } + } +} + +// !JIM! 08/06 +extern BOOL UsingMenus; + +#if 0 +VOID +ViewOutsidePlayerRecurse(PLAYERp pp, LONGp vx, LONGp vy, LONGp vz, SHORTp ang, SHORTp vsectnum) +{ + int nx, ny; + int ret; + + *vx = pp->posx; + *vy = pp->posy; + *vz = pp->posz; + *vsectnum = pp->cursectnum; + + *ang = pp->pang + pp->view_outside_dang; + + nx = sintable[NORM_ANGLE(*ang + 512 + 1024)] << 11; + ny = sintable[NORM_ANGLE(*ang + 1024)] << 11; + + ret = clipmove(vx, vy, vz, vsectnum, nx, ny, 64L, 4 << 8, 4 << 8, CLIPMASK_PLAYER); + + switch (TEST(ret, HIT_MASK)) + { + case HIT_SPRITE: + { + short hitsprite; + SPRITEp sp; + + hitsprite = NORM_SPRITE(ret); + sp = &sprite[hitsprite]; + + // if you hit a sprite that's not a wall sprite - try again + if (!TEST(sp->cstat, CSTAT_SPRITE_WALL)) + { + FLIP(sp->cstat, CSTAT_SPRITE_BLOCK); + ViewOutsidePlayerRecurse(pp, vx, vy, vz, ang, vsectnum); + FLIP(sp->cstat, CSTAT_SPRITE_BLOCK); + } + + break; + } + } + + if (TEST(sector[*vsectnum].floorstat, FLOOR_STAT_SLOPE)|TEST(sector[*vsectnum].ceilingstat, CEILING_STAT_SLOPE)) + { + int cz, fz; + + getzsofslope(*vsectnum, *vx, *vy, &cz, &fz); + + if (*vz > fz - Z(12)) + *vz = fz - Z(12); + + if (*vz < cz + Z(12)) + *vz = cz + Z(12); + + } +} +#endif + + + +void +BackView(int *nx, int *ny, int *nz, short *vsect, short *nang, short horiz) +{ + SPRITEp sp; + int i, vx, vy, vz, hx, hy, hz, hitx, hity, hitz; + short bakcstat, hitsect, hitwall, hitsprite, daang; + PLAYERp pp = &Player[screenpeek]; + short ang; + + ASSERT(*vsect >= 0 && *vsect < MAXSECTORS); + + ang = *nang + pp->view_outside_dang; + + // Calculate the vector (nx,ny,nz) to shoot backwards + vx = (sintable[NORM_ANGLE(ang + 1536)] >> 3); + vy = (sintable[NORM_ANGLE(ang + 1024)] >> 3); + vz = (horiz - 100) * 256L; + + // Player sprite of current view + sp = &sprite[pp->PlayerSprite]; + + bakcstat = sp->cstat; + RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + + // Make sure sector passed to FAFhitscan is correct + //COVERupdatesector(*nx, *ny, vsect); + + hitscan(*nx, *ny, *nz, *vsect, vx, vy, vz, + &hitsect, &hitwall, &hitsprite, &hitx, &hity, &hitz, CLIPMASK_PLAYER); + + ASSERT(*vsect >= 0 && *vsect < MAXSECTORS); + + sp->cstat = bakcstat; // Restore cstat + + hx = hitx - (*nx); + hy = hity - (*ny); + + // If something is in the way, make pp->camera_dist lower if necessary + if (klabs(vx) + klabs(vy) > klabs(hx) + klabs(hy)) + { + if (hitwall >= 0) // Push you a little bit off the wall + { + *vsect = hitsect; + + daang = getangle(wall[wall[hitwall].point2].x - wall[hitwall].x, + wall[wall[hitwall].point2].y - wall[hitwall].y); + + i = vx * sintable[daang] + vy * sintable[NORM_ANGLE(daang + 1536)]; + if (klabs(vx) > klabs(vy)) + hx -= mulscale28(vx, i); + else + hy -= mulscale28(vy, i); + } + else if (hitsprite < 0) // Push you off the ceiling/floor + { + *vsect = hitsect; + + if (klabs(vx) > klabs(vy)) + hx -= (vx >> 5); + else + hy -= (vy >> 5); + } + else + { + SPRITEp hsp = &sprite[hitsprite]; + int flag_backup; + + // if you hit a sprite that's not a wall sprite - try again + if (!TEST(hsp->cstat, CSTAT_SPRITE_WALL)) + { + flag_backup = hsp->cstat; + RESET(hsp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + ASSERT(*vsect >= 0 && *vsect < MAXSECTORS); + BackView(nx, ny, nz, vsect, nang, horiz); + hsp->cstat = flag_backup; + return; + } + else + { + // same as wall calculation + daang = NORM_ANGLE(sp->ang-512); + + i = vx * sintable[daang] + vy * sintable[NORM_ANGLE(daang + 1536)]; + if (klabs(vx) > klabs(vy)) + hx -= mulscale28(vx, i); + else + hy -= mulscale28(vy, i); + } + + } + + if (klabs(vx) > klabs(vy)) + i = (hx << 16) / vx; + else + i = (hy << 16) / vy; + + if (i < pp->camera_dist) + pp->camera_dist = i; + } + + // Actually move you! (Camerdist is 65536 if nothing is in the way) + *nx = (*nx) + mulscale16(vx, pp->camera_dist); + *ny = (*ny) + mulscale16(vy, pp->camera_dist); + *nz = (*nz) + mulscale16(vz, pp->camera_dist); + + // Slowly increase pp->camera_dist until it reaches 65536 + // Synctics is a timer variable so it increases the same rate + // on all speed computers + pp->camera_dist = min(pp->camera_dist + (3 << 10), 65536); + //pp->camera_dist = min(pp->camera_dist + (synctics << 10), 65536); + + // Make sure vsect is correct + updatesectorz(*nx, *ny, *nz, vsect); + + *nang = ang; +} + +void +CircleCamera(int *nx, int *ny, int *nz, short *vsect, short *nang, short horiz) +{ + SPRITEp sp; + int i, vx, vy, vz, hx, hy, hz, hitx, hity, hitz; + short bakcstat, hitsect, hitwall, hitsprite, daang; + PLAYERp pp = &Player[screenpeek]; + short ang; + + ang = *nang + pp->circle_camera_ang; + + // Calculate the vector (nx,ny,nz) to shoot backwards + vx = (sintable[NORM_ANGLE(ang + 1536)] >> 4); + vy = (sintable[NORM_ANGLE(ang + 1024)] >> 4); + + // lengthen the vector some + vx += DIV2(vx); + vy += DIV2(vy); + + vz = (horiz - 100) * 256; + + // Player sprite of current view + sp = &sprite[pp->PlayerSprite]; + + bakcstat = sp->cstat; + RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + + // Make sure sector passed to hitscan is correct + //COVERupdatesector(*nx, *ny, vsect); + + hitscan(*nx, *ny, *nz, *vsect, vx, vy, vz, + &hitsect, &hitwall, &hitsprite, &hitx, &hity, &hitz, CLIPMASK_MISSILE); + + sp->cstat = bakcstat; // Restore cstat + //ASSERT(hitsect >= 0); + + hx = hitx - (*nx); + hy = hity - (*ny); + + // If something is in the way, make pp->circle_camera_dist lower if necessary + if (klabs(vx) + klabs(vy) > klabs(hx) + klabs(hy)) + { + if (hitwall >= 0) // Push you a little bit off the wall + { + *vsect = hitsect; + + daang = getangle(wall[wall[hitwall].point2].x - wall[hitwall].x, + wall[wall[hitwall].point2].y - wall[hitwall].y); + + i = vx * sintable[daang] + vy * sintable[NORM_ANGLE(daang + 1536)]; + if (klabs(vx) > klabs(vy)) + hx -= mulscale28(vx, i); + else + hy -= mulscale28(vy, i); + } + else if (hitsprite < 0) // Push you off the ceiling/floor + { + *vsect = hitsect; + + if (klabs(vx) > klabs(vy)) + hx -= (vx >> 5); + else + hy -= (vy >> 5); + } + else + { + SPRITEp hsp = &sprite[hitsprite]; + int flag_backup; + + // if you hit a sprite that's not a wall sprite - try again + if (!TEST(hsp->cstat, CSTAT_SPRITE_WALL)) + { + flag_backup = hsp->cstat; + RESET(hsp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + + CircleCamera(nx, ny, nz, vsect, nang, horiz); + hsp->cstat = flag_backup; + return; + } + } + + if (klabs(vx) > klabs(vy)) + i = (hx << 16) / vx; + else + i = (hy << 16) / vy; + + if (i < pp->circle_camera_dist) + pp->circle_camera_dist = i; + } + + // Actually move you! (Camerdist is 65536 if nothing is in the way) + *nx = (*nx) + ((vx * pp->circle_camera_dist) >> 16); + *ny = (*ny) + ((vy * pp->circle_camera_dist) >> 16); + *nz = (*nz) + ((vz * pp->circle_camera_dist) >> 16); + + // Slowly increase pp->circle_camera_dist until it reaches 65536 + // Synctics is a timer variable so it increases the same rate + // on all speed computers + pp->circle_camera_dist = min(pp->circle_camera_dist + (3 << 8), 65536); + //pp->circle_camera_dist = min(pp->circle_camera_dist + (synctics << 10), 65536); + + // Make sure vsect is correct + updatesectorz(*nx, *ny, *nz, vsect); + + *nang = ang; +} + +VOID PrintLocationInfo(PLAYERp pp) +{ +#define Y_STEP 7 +#define AVERAGEFRAMES 16 + int x = windowx1+2; + int y = windowy1+2; + static int frameval[AVERAGEFRAMES], framecnt = 0; + int i; + + if (LocationInfo) + { + + i = totalclock; + if (i != frameval[framecnt]) + { + sprintf(tempbuf, "FPS: %d", ((120 * AVERAGEFRAMES) / (i - frameval[framecnt])) + f_c); + printext256(x, y, 1, -1, tempbuf, 1); + frameval[framecnt] = i; + } + + framecnt = ((framecnt + 1) & (AVERAGEFRAMES - 1)); + + if (LocationInfo > 1) + { + y += Y_STEP; + + sprintf(buffer, "POSX:%d", pp->posx); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "POSY:%d", pp->posy); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "POSZ:%d", pp->posz); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "ANG:%d", (LONG) pp->pang); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + } + } +} + +BOOL DebugSecret = FALSE; +VOID SecretInfo(PLAYERp pp) +{ +#define Y_STEP 7 +#define AVERAGEFRAMES 16 + int x = windowx1+2; + int y = windowy1+2+8; + extern short LevelSecrets,TotalKillable; + + if (CommEnabled || numplayers > 1) + return; + + x = x / (xdim/320.0); + y = y / (ydim/200.0); + + if (gs.Stats) + { + sprintf(ds, "Kills %d/%d", Player->Kills, TotalKillable); + DisplayMiniBarSmString(pp, x, y, PAL_XLAT_BROWN, ds); + + sprintf(ds, "Secrets %d/%d", Player->SecretsFound, LevelSecrets); + DisplayMiniBarSmString(pp, x, y+10, PAL_XLAT_BROWN, ds); + } +} + +VOID PrintSpriteInfo(PLAYERp pp) +{ +#define Y_STEP 7 + int x = windowx1+2; + int y = windowy1+2; + SPRITEp sp; + USERp u; + short hitsprite; + + if (SpriteInfo && !LocationInfo) + { + hitsprite = DoPickTarget(pp->SpriteP, 32, 2); + + sp = &sprite[hitsprite]; + u = User[hitsprite]; + + sp->hitag = 9997; // Special tag to make the actor glow red for one frame + + y += Y_STEP; + + if (hitsprite == -1) + { + sprintf(buffer, "SPRITENUM: NONE TARGETED"); + printext256(x, y, 1, -1, buffer, 1); + return; + } + else + sprintf(buffer, "SPRITENUM:%d", hitsprite); + + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + if (u) + { + sprintf(buffer, "ID:%d", u->ID); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "PALETTE:%d", u->spal); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "HEALTH:%d", u->Health); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "WAITTICS:%d", u->WaitTics); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "COUNTER:%d", u->Counter); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "COUNTER2:%d", u->Counter); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + } + if (SpriteInfo > 1) + { + sprintf(buffer, "POSX:%d", sp->x); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "POSY:%d", sp->y); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "POSZ:%d", sp->z); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + sprintf(buffer, "ANG:%d", (LONG) sp->ang); + printext256(x, y, 1, -1, buffer, 1); + y += Y_STEP; + } + } +} + + +VOID SpriteSortList2D(int tx, int ty) +{ + SPRITEp sp; + int i; + int dist,a,b,c; + + spritesortcnt = 0; + for (i = 0; i < MAXSPRITES; i++) + { + if (sprite[i].statnum < MAXSTATUS) + { + sp = &sprite[i]; + + if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE) && + (sp->xrepeat > 0) && (sp->yrepeat > 0) && + (spritesortcnt < MAXSPRITESONSCREEN)) + { + DISTANCE(tx,ty,sp->x,sp->y,dist,a,b,c); + + if (dist < 22000) + { + memcpy(&tsprite[spritesortcnt], sp, sizeof(SPRITE)); + tsprite[spritesortcnt++].owner = i; + } + } + } + } +} + +int COVERsetgamemode(int mode, int xdim, int ydim, int bpp) +{ + extern int ScreenHeight, ScreenWidth, ScreenMode, ScreenBPP; + + + ScreenHeight = ydim; + ScreenWidth = xdim; + ScreenMode = mode; + ScreenBPP = bpp; + + return (int)setgamemode(mode,xdim,ydim,bpp); +} + +void CheatResChange(void) +{ + /* + extern char permanentupdate; + int i; + + // needs to be called from drawscreen - crashes otherwise + + //cycle through all vesa modes, then screen-buffer mode + if (vidoption == 1) + { + for(i=0;i < validmodecnt;i++) + { + if ((validmodexdim[i] == xdim) && (validmodeydim[i] == ydim)) + { + if (i == validmodecnt-1) + COVERsetgamemode(2,320L,200L); + else + COVERsetgamemode(1,validmodexdim[i+1],validmodeydim[i+1]); + break; + } + } + } + else + { + if (validmodecnt > 0) + COVERsetgamemode(1,validmodexdim[0],validmodeydim[0]); + } + + permanentupdate = 0; + + SetupAspectRatio(); + SetRedrawScreen(Player + myconnectindex); + + sprintf(ds,"%d x %d mode selected.", xdim, ydim); + PutStringInfo(Player + myconnectindex, ds); + */ + PutStringInfo(Player + myconnectindex, "JonoF: Not now"); +} + +#if 0 +void ResChange(void) +{ + extern char permanentupdate; + int i; + + static short sw_res[5]; + static short res_ndx=0; + + // clear pages before and after res set for good measure + for (i = 0; i < numpages; i++) + { + clearview(0); + nextpage(); + } + + // needs to be called from drawscreen - crashes otherwise + + if (res_ndx == 0) + { + // choose resolutions for shadow warrior + for (i=0; i < validmodecnt; i++) + { + if (validmodexdim[i] + validmodeydim[i] == 320 + 200) + sw_res[res_ndx++] = i; + else if (validmodexdim[i] + validmodeydim[i] == 640 + 400) + sw_res[res_ndx++] = i; + else if (validmodexdim[i] + validmodeydim[i] == 640 + 480) + sw_res[res_ndx++] = i; + else if (validmodexdim[i] + validmodeydim[i] == 800 + 600) + sw_res[res_ndx++] = i; + } + } + + //cycle through all sw modes, then screen-buffer mode + if (vidoption == 1) + { + for (i = 0; i < res_ndx; i++) + { + if ((validmodexdim[sw_res[i]] == xdim) && (validmodeydim[sw_res[i]] == ydim)) + { + if (i >= res_ndx-1) + COVERsetgamemode(2, 320L, 200L); + else + COVERsetgamemode(1, validmodexdim[sw_res[i+1]], validmodeydim[sw_res[i+1]]); + break; + } + } + + + // if did not find current res then reset to 320x200 + if (i >= res_ndx) + COVERsetgamemode(2, 320L, 200L); + } + else + { + if (validmodecnt > 0) + COVERsetgamemode(1, validmodexdim[0], validmodeydim[0]); + } + + permanentupdate = 0; + + for (i = 0; i < numpages; i++) + { + clearview(0); + nextpage(); + } + + SetupAspectRatio(); + SetRedrawScreen(Player + myconnectindex); + + sprintf(ds,"%d x %d mode selected.", xdim, ydim); + PutStringInfo(Player + myconnectindex, ds); +} +#endif + +VOID ScreenCaptureKeys(VOID) +{ + if (ConPanel) + return; + + // screen capture + if (KEY_PRESSED(KEYSC_F12)) + { + KEY_PRESSED(KEYSC_F12) = 0; + PauseAction(); + screencapture("swcpxxxx.pcx", KEY_PRESSED(KEYSC_LSHIFT) | KEY_PRESSED(KEYSC_LSHIFT)); + ResumeAction(); + PutStringInfo(Player + myconnectindex, "Screen Captured"); + } +} + +VOID DrawCheckKeys(PLAYERp pp) +{ + extern BOOL ResCheat; + extern BOOL PauseKeySet; + + /* JonoF: Who really needs this now? + if (KEY_PRESSED(KEYSC_F5) && !(KEY_PRESSED(KEYSC_RSHIFT) || KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_ALT) || KEY_PRESSED(KEYSC_RALT)) && !PauseKeySet) + { + KEY_PRESSED(KEYSC_F5) = 0; + ResChange(); + } + */ + + if (ResCheat) + { + ResCheat = FALSE; + CheatResChange(); // allow all modes when cheating + } + + if (ConPanel) return; + + if (!InputMode) + ResizeView(pp); + + ScreenCaptureKeys(); +} + +#if 0 +VOID DrawMessageInput(PLAYERp pp) +{ + short w,h; + static BOOL cur_show; + short c; + + // Used to make cursor fade in and out + c = 4-(sintable[(totalclock<<4)&2047]>>11); + + if (MessageInputMode) + { + MNU_MeasureString(MessageInputString, &w, &h); + + cur_show ^= 1; + if (cur_show) + { + MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,ROTATE_SPRITE_SCREEN_CLIP); + rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),c,0, + (ROTATE_SPRITE_SCREEN_CLIP),0,0,xdim-1,ydim-1); + } + else + { + MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,ROTATE_SPRITE_SCREEN_CLIP); + rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),c,0, + (ROTATE_SPRITE_SCREEN_CLIP),0,0,xdim-1,ydim-1); + } + } +} +#else +VOID DrawMessageInput(PLAYERp pp) +{ + short w,h; + static BOOL cur_show; + short c; + + // Used to make cursor fade in and out + c = 4-(sintable[(totalclock<<4)&2047]>>11); + + if (MessageInputMode) + { + MNU_MeasureSmallString(MessageInputString, &w, &h); + + cur_show ^= 1; + if (cur_show) + { + minigametext(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,0,ROTATE_SPRITE_SCREEN_CLIP); + rotatesprite((TEXT_XCENTER(w)+w+2)<<16,(MESSAGE_LINE+1)<<16,20000,0,COINCURSOR+((totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1); + } + else + { + minigametext(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,0,ROTATE_SPRITE_SCREEN_CLIP); + rotatesprite((TEXT_XCENTER(w)+w+2)<<16,(MESSAGE_LINE+1)<<16,20000,0,COINCURSOR+((totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1); + } + } +} +#endif + +VOID DrawConInput(PLAYERp pp) +{ +#define PANELINPUTX 30 +#define PANELINPUTY 100 + short w,h; + static BOOL cur_show; + short c; + + // Used to make cursor fade in and out + c = 4-(sintable[(totalclock<<4)&2047]>>11); + + if (ConInputMode) + { + MNU_MeasureSmallString(MessageInputString, &w, &h); + + cur_show ^= 1; + if (cur_show) + { + MNU_DrawSmallString(PANELINPUTX, PANELINPUTY, MessageInputString,1,17); + rotatesprite((PANELINPUTX+w+1)<<16,(PANELINPUTY)<<16,65536L,0,2992,c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1); + //rotatesprite((PANELINPUTX+w+3)<<16,(PANELINPUTY)<<16,64<<8,0,COINCURSOR+((totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1); + } + else + { + MNU_DrawSmallString(PANELINPUTX, PANELINPUTY, MessageInputString,1,17); + rotatesprite((PANELINPUTX+w+1)<<16,(PANELINPUTY)<<16,65536L,0,2992,c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1); + //rotatesprite((PANELINPUTX+w+3)<<16,(PANELINPUTY)<<16,64<<8,0,COINCURSOR+((totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1); + } + } +} + +VOID DrawCrosshair(PLAYERp pp) +{ + extern int CrosshairX, CrosshairY; + extern BOOL DemoMode,CameraTestMode; + + if (!gs.Crosshair) + return; + + if (DemoMode || CameraTestMode) + return; + + if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) + return; + + if (dimensionmode == 6) + return; + +// wdx = 160; +// wdy = 100; +#if 0 + if (gs.AutoAim) + { + int daz; + short hitsprite, daang; + static int handle=-1; + + daz = pp->posz + pp->bob_z; + daang = 32; + if ((hitsprite = WeaponAutoAimHitscan(pp->SpriteP, &daz, &daang, FALSE)) != -1) + { + SPRITEp hp = &sprite[hitsprite]; + USERp hu = User[hitsprite]; + int dx,dy,dz; + + + // Find the delta coordinates from player to monster that is targeted + dx = hp->x - pp->posx; + dy = hp->y - pp->posy; + dz = ((hp->z - (SPRITE_SIZE_Z(hitsprite)/2)) - pp->posz) >> 4; + + rotatepoint(0,0,dx,dy,(-pp->pang)&2047,&dx,&dy); + + if (dx == 0) return; + + wdx = windowx1 + ((windowx2-windowx1)/2); + wdy = windowy1 + ((windowy2-windowy1)/2); + + x = (dy * wdx << 8) / dx + (wdx << 8); + y = (dz * wdx << 8) / dx + (wdy << 8); + + y -= 100; + y += (pp->horiz*wdx)/160; + + if (pp->CurWpn == pp->Wpn[WPN_RAIL]) + { + if (!FX_SoundActive(handle)) + handle = PlaySound(DIGI_RAILLOCKED, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + } + } + else + { + // It didn't target anything. + if (pp->CurWpn == pp->Wpn[WPN_RAIL]) + { + if (FX_SoundActive(handle)) + FX_StopSound(handle); + } + goto NORMALXHAIR; + } + + rotatesprite(x << 8, y << 8, (1 << 16), 0, + 2326, 10, 0, + ROTATE_SPRITE_VIEW_CLIP|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + } + else +#endif + { +//NORMALXHAIR: + rotatesprite(CrosshairX, CrosshairY, (1 << 16), 0, + 2326, 10, 0, + //ROTATE_SPRITE_VIEW_CLIP|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + } + + //#define TITLE_ROT_FLAGS (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK) + +} + +void CameraView(PLAYERp pp, int *tx, int *ty, int *tz, short *tsectnum, short *tang, int *thoriz) +{ + int i,nexti; + short ang; + SPRITEp sp; + BOOL found_camera = FALSE; + BOOL player_in_camera = FALSE; + BOOL FAFcansee_test; + BOOL ang_test; + + if (pp == &Player[screenpeek]) + { + TRAVERSE_SPRITE_STAT(headspritestat[STAT_DEMO_CAMERA], i, nexti) + { + sp = &sprite[i]; + + ang = getangle(*tx - sp->x, *ty - sp->y); + ang_test = GetDeltaAngle(sp->ang, ang) < sp->lotag; + + FAFcansee_test = + (FAFcansee(sp->x, sp->y, sp->z, sp->sectnum, *tx, *ty, *tz, pp->cursectnum) || + FAFcansee(sp->x, sp->y, sp->z, sp->sectnum, *tx, *ty, *tz + SPRITEp_SIZE_Z(pp->SpriteP), pp->cursectnum)); + + player_in_camera = ang_test && FAFcansee_test; + + if (player_in_camera || pp->camera_check_time_delay > 0) + { + + // if your not in the camera but are still looking + // make sure that only the last camera shows you + + if (!player_in_camera && pp->camera_check_time_delay > 0) + { + if (pp->last_camera_sp != sp) + continue; + } + + switch (sp->clipdist) + { + case 1: + pp->last_camera_sp = sp; + CircleCamera(tx, ty, tz, tsectnum, tang, 100); + found_camera = TRUE; + break; + + default: + { + int xvect,yvect,zvect,zdiff; + + pp->last_camera_sp = sp; + + xvect = sintable[NORM_ANGLE(ang + 512)] >> 3; + yvect = sintable[NORM_ANGLE(ang)] >> 3; + + zdiff = sp->z - *tz; + if (labs(sp->x - *tx) > 1000) + zvect = scale(xvect, zdiff, sp->x - *tx); + else if (labs(sp->y - *ty) > 1000) + zvect = scale(yvect, zdiff, sp->y - *ty); + else if (sp->x - *tx != 0) + zvect = scale(xvect, zdiff, sp->x - *tx); + else if (sp->y - *ty != 0) + zvect = scale(yvect, zdiff, sp->y - *ty); + else + zvect = 0; + + // new horiz to player + *thoriz = 100 - (zvect/256); + *thoriz = max(*thoriz, PLAYER_HORIZ_MIN); + *thoriz = min(*thoriz, PLAYER_HORIZ_MAX); + + //DSPRINTF(ds,"xvect %d,yvect %d,zvect %d,thoriz %d",xvect,yvect,zvect,*thoriz); + MONO_PRINT(ds); + + *tang = ang; + *tx = sp->x; + *ty = sp->y; + *tz = sp->z; + *tsectnum = sp->sectnum; + + found_camera = TRUE; + break; + } + } + } + + if (found_camera) + break; + } + } + + // if you player_in_camera you definately have a camera + if (player_in_camera) + { + pp->camera_check_time_delay = 120/2; + SET(pp->Flags, PF_VIEW_FROM_CAMERA); + + ASSERT(found_camera); + } + else + // if you !player_in_camera you still might have a camera + // for a split second + { + if (found_camera) + { + SET(pp->Flags, PF_VIEW_FROM_CAMERA); + } + else + { + pp->circle_camera_ang = 0; + pp->circle_camera_dist = CIRCLE_CAMERA_DIST_MIN; + RESET(pp->Flags, PF_VIEW_FROM_CAMERA); + } + } +} + +VOID +PreDraw(VOID) +{ + short i, nexti; + + PreDrawStackedWater(); + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FLOOR_SLOPE_DONT_DRAW], i, nexti) + { + RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_SLOPE); + } +} + +VOID +PostDraw(VOID) +{ + short i, nexti; + short sectnum,statnum; + SPRITEp sp; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FLOOR_SLOPE_DONT_DRAW], i, nexti) + { + SET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_SLOPE); + } + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF_COPY], i, nexti) + { + if (User[i]) + { + FreeMem(User[i]); + User[i] = NULL; + } + +#if DEBUG + sp = &sprite[i]; + statnum = sp->statnum; + sectnum = sp->sectnum; + memset(sp, 0xCC, sizeof(SPRITE)); + sp->statnum = statnum; + sp->sectnum = sectnum; +#endif + + deletesprite(i); + } +} + +int CopySprite(SPRITEp tsp, short newsector) +{ + short new; + SPRITEp sp; + + new = COVERinsertsprite(newsector, STAT_FAF_COPY); + sp = &sprite[new]; + + sp->x = tsp->x; + sp->y = tsp->y; + sp->z = tsp->z; + sp->cstat = tsp->cstat; + sp->picnum = tsp->picnum; + sp->pal = tsp->pal; + sp->xrepeat = tsp->xrepeat; + sp->yrepeat = tsp->yrepeat; + sp->xoffset = tsp->xoffset; + sp->yoffset = tsp->yoffset; + sp->ang = tsp->ang; + sp->xvel = tsp->xvel; + sp->yvel = tsp->yvel; + sp->zvel = tsp->zvel; + sp->shade = tsp->shade; + + RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); + + return new; +} + +int ConnectCopySprite(SPRITEp tsp) +{ + short newsector; + int testz; + + if (FAF_ConnectCeiling(tsp->sectnum)) + { + newsector = tsp->sectnum; + testz = SPRITEp_TOS(tsp) - Z(10); + + if (testz < sector[tsp->sectnum].ceilingz) + updatesectorz(tsp->x, tsp->y, testz, &newsector); + + if (newsector >= 0 && newsector != tsp->sectnum) + { + return CopySprite(tsp, newsector); + } + } + + if (FAF_ConnectFloor(tsp->sectnum)) + { + newsector = tsp->sectnum; + testz = SPRITEp_BOS(tsp) + Z(10); + + if (testz > sector[tsp->sectnum].floorz) + updatesectorz(tsp->x, tsp->y, testz, &newsector); + + if (newsector >= 0 && newsector != tsp->sectnum) + { + return CopySprite(tsp, newsector); + } + } + + return -1; +} + + +void PreDrawStackedWater(void) +{ + short si,snexti; + short i,nexti; + SPRITEp sp,np; + USERp u,nu; + short new; + int smr4,smr2; + int x,y,z; + short ang; + PLAYERp pp = Player + screenpeek; + + smr4 = smoothratio + (((int) MoveSkip4) << 16); + smr2 = smoothratio + (((int) MoveSkip2) << 16); + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], si, snexti) + { + TRAVERSE_SPRITE_SECT(headspritesect[sprite[si].sectnum], i, nexti) + { + if (User[i]) + { + if (sprite[i].statnum == STAT_ITEM) + continue; + + if (sprite[i].statnum <= STAT_DEFAULT || sprite[i].statnum > STAT_PLAYER0 + MAX_SW_PLAYERS) + continue; + + // code so that a copied sprite will not make another copy + if (User[i]->xchange == -989898) + continue; + + sp = &sprite[i]; + u = User[i]; + + new = ConnectCopySprite(sp); + if (new >= 0) + { + np = &sprite[new]; + + // spawn a user + User[new] = nu = (USERp)CallocMem(sizeof(USER), 1); + ASSERT(nu != NULL); + + nu->xchange = -989898; + + // copy everything reasonable from the user that + // analyzesprites() needs to draw the image + nu->State = u->State; + nu->Rot = u->Rot; + nu->StateStart = u->StateStart; + nu->StateEnd = u->StateEnd; + nu->ox = u->ox; + nu->oy = u->oy; + nu->oz = u->oz; + nu->Flags = u->Flags; + nu->Flags2 = u->Flags2; + nu->RotNum = u->RotNum; + nu->ID = u->ID; + + // set these to other sprite for players draw + nu->SpriteNum = i; + nu->SpriteP = sp; + + nu->PlayerP = u->PlayerP; + nu->spal = u->spal; + } + } + } + } +} + + +void FAF_DrawRooms(int x, int y, int z, short ang, int horiz, short sectnum) +{ + short i,nexti; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], i, nexti) + { + if (SPRITE_TAG3(i) == 0) + { + // back up ceilingpicnum and ceilingstat + SPRITE_TAG5(i) = sector[sprite[i].sectnum].ceilingpicnum; + sector[sprite[i].sectnum].ceilingpicnum = SPRITE_TAG2(i); + SPRITE_TAG4(i) = sector[sprite[i].sectnum].ceilingstat; + //SET(sector[sprite[i].sectnum].ceilingstat, ((int)SPRITE_TAG7(i))<<7); + SET(sector[sprite[i].sectnum].ceilingstat, SPRITE_TAG6(i)); + RESET(sector[sprite[i].sectnum].ceilingstat, CEILING_STAT_PLAX); + } + else if (SPRITE_TAG3(i) == 1) + { + SPRITE_TAG5(i) = sector[sprite[i].sectnum].floorpicnum; + sector[sprite[i].sectnum].floorpicnum = SPRITE_TAG2(i); + SPRITE_TAG4(i) = sector[sprite[i].sectnum].floorstat; + //SET(sector[sprite[i].sectnum].floorstat, ((int)SPRITE_TAG7(i))<<7); + SET(sector[sprite[i].sectnum].floorstat, SPRITE_TAG6(i)); + RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_PLAX); + } + } + + drawrooms(x,y,z,ang,horiz,sectnum); + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], i, nexti) + { + // manually set gotpic + if (TEST_GOTSECTOR(sprite[i].sectnum)) + { + SET_GOTPIC(FAF_MIRROR_PIC); + } + + if (SPRITE_TAG3(i) == 0) + { + // restore ceilingpicnum and ceilingstat + sector[sprite[i].sectnum].ceilingpicnum = SPRITE_TAG5(i); + sector[sprite[i].sectnum].ceilingstat = SPRITE_TAG4(i); + //RESET(sector[sprite[i].sectnum].ceilingstat, CEILING_STAT_TYPE_MASK); + RESET(sector[sprite[i].sectnum].ceilingstat, CEILING_STAT_PLAX); + } + else if (SPRITE_TAG3(i) == 1) + { + sector[sprite[i].sectnum].floorpicnum = SPRITE_TAG5(i); + sector[sprite[i].sectnum].floorstat = SPRITE_TAG4(i); + //RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_TYPE_MASK); + RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_PLAX); + } + } +} + +short ScreenSavePic = FALSE; + +VOID +drawscreen(PLAYERp pp) +{ + extern BOOL DemoMode,CameraTestMode; + int tx, ty, tz,thoriz,pp_siz; + short tang,tsectnum; + short i,j; + walltype *wal; + int tiltlock; + int bob_amt = 0; + int quake_z, quake_x, quake_y; + short quake_ang; + BOOL PicInView(short, BOOL); + extern BOOL FAF_DebugView; + PLAYERp camerapp; // prediction player if prediction is on, else regular player + VOID DoPlayerDiveMeter(PLAYERp pp); + + // last valid stuff + static short lv_sectnum = -1; + static int lv_x, lv_y, lv_z; + + if (HelpInputMode) + { + flushperms(); + // note - could put Order Info Pages at the top like this also + + rotatesprite(0,0,65536L,0,HelpPagePic[HelpPage],0,0, + (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST), + 0, 0, xdim-1, ydim-1); + nextpage(); + + return; + } + +#if 0 + if (TenScreenMode) + { +#define TEN_PIC 5109 + + flushperms(); + // note - could put Order Info Pages at the top like this also + rotatesprite(0,0,65536L,0,TEN_PIC,0,0, + (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST), + 0, 0, xdim-1, ydim-1); + + nextpage(); + return; + } +#endif + + if (getrendermode() >= 3) + RedrawScreen = TRUE; + + DrawScreen = TRUE; + PreDraw(); + // part of new border refresh method + if (RedrawScreen) + { + RedrawCompass = TRUE; + RedrawScreen = FALSE; + // get rid of all PERM sprites! + flushperms(); + // get rid of all PANF_KILL_AFTER_SHOW sprites! + pFlushPerms(pp); + SetBorder(pp,gs.BorderNum); + } + + PreUpdatePanel(); + + + smoothratio = min(max((totalclock - ototalclock) * (65536 / synctics),0),65536); + + if (!ScreenSavePic) + { + dointerpolations(smoothratio); // Stick at beginning of drawscreen + short_dointerpolations(smoothratio); // Stick at beginning of drawscreen + } + + // TENSW: when rendering with prediction, the only thing that counts should + // be the predicted player. + if (PredictionOn && CommEnabled && pp == Player+myconnectindex) + camerapp = ppp; + else + camerapp = pp; + + tx = camerapp->oposx + mulscale(camerapp->posx - camerapp->oposx, smoothratio, 16); + ty = camerapp->oposy + mulscale(camerapp->posy - camerapp->oposy, smoothratio, 16); + tz = camerapp->oposz + mulscale(camerapp->posz - camerapp->oposz, smoothratio, 16); + tang = camerapp->oang + mulscale(((camerapp->pang + 1024 - camerapp->oang) & 2047) - 1024, smoothratio, 16); + thoriz = camerapp->ohoriz + mulscale(camerapp->horiz - camerapp->ohoriz, smoothratio, 16); + tsectnum = camerapp->cursectnum; + + //ASSERT(tsectnum >= 0 && tsectnum <= MAXSECTORS); + // if updatesectorz is to sensitive try COVERupdatesector + //updatesectorz(tx, ty, tz, &tsectnum); + + COVERupdatesector(tx, ty, &tsectnum); + + if (tsectnum < 0) + { + // if we hit an invalid sector move to the last valid position for drawing + tsectnum = lv_sectnum; + tx = lv_x; + ty = lv_y; + tz = lv_z; + } + else + { + // last valid stuff + lv_sectnum = tsectnum; + lv_x = tx; + lv_y = ty; + lv_z = tz; + } + + // with "last valid" code this should never happen + ASSERT(tsectnum >= 0 && tsectnum <= MAXSECTORS); + + pp->six = tx; + pp->siy = ty; + pp->siz = tz - pp->posz; + pp_siz = tz; + pp->siang = tang; + + if (pp->sop_riding || pp->sop_control) + { + tx = pp->posx; + ty = pp->posy; + tz = pp->posz; + tang = pp->pang; + tsectnum = pp->cursectnum; + updatesectorz(tx, ty, tz, &tsectnum); + + pp->six = tx; + pp->siy = ty; + pp->siz = tz - pp->posz; + pp->siang = tang; + } + + QuakeViewChange(camerapp, &quake_z, &quake_x, &quake_y, &quake_ang); + VisViewChange(camerapp, &visibility); + tz = tz + quake_z; + tx = tx + quake_x; + ty = ty + quake_y; + //thoriz = thoriz + quake_x; + tang = NORM_ANGLE(tang + quake_ang); + + if (pp->sop_remote) + { + if (TEST_BOOL1(pp->remote_sprite)) + tang = pp->remote_sprite->ang; + else + tang = getangle(pp->sop_remote->xmid - tx, pp->sop_remote->ymid - ty); + } + + //if (TEST(camerapp->Flags, PF_VIEW_FROM_OUTSIDE)) + if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) + { + BackView(&tx, &ty, &tz, &tsectnum, &tang, thoriz); + } + else + { + bob_amt = camerapp->bob_amt; + + if (DemoMode || CameraTestMode) + CameraView(camerapp, &tx, &ty, &tz, &tsectnum, &tang, &thoriz); + } + + if (!TEST(pp->Flags, PF_VIEW_FROM_CAMERA|PF_VIEW_FROM_OUTSIDE)) + { + tz += bob_amt; + tz += camerapp->bob_z; + + // recoil only when not in camera + //thoriz = thoriz + camerapp->recoil_horizoff; + thoriz = thoriz + pp->recoil_horizoff; + thoriz = max(thoriz, PLAYER_HORIZ_MIN); + thoriz = min(thoriz, PLAYER_HORIZ_MAX); + } + + if (FAF_DebugView) + clearview(255); + + OverlapDraw = TRUE; + DrawOverlapRoom(tx, ty, tz, tang, thoriz, tsectnum); + OverlapDraw = FALSE; + + if (dimensionmode != 6 && !ScreenSavePic) + { + // TEST this! Changed to camerapp + //JS_DrawMirrors(camerapp, tx, ty, tz, tang, thoriz); + JS_DrawMirrors(pp, tx, ty, tz, tang, thoriz); + } + + if (!FAF_DebugView) + { + FAF_DrawRooms(tx, ty, tz, tang, thoriz, tsectnum); + PicInView(FAF_MIRROR_PIC, FALSE); + } + + analyzesprites(tx, ty, tz, FALSE); + post_analyzesprites(); + drawmasks(); + + UpdatePanel(); + +#define SLIME 2305 + // Only animate lava if its picnum is on screen + // gotpic is a bit array where the tile number's bit is set + // whenever it is drawn (ceilings, walls, sprites, etc.) + if ((gotpic[SLIME >> 3] & (1 << (SLIME & 7))) > 0) + { + gotpic[SLIME >> 3] &= ~(1 << (SLIME & 7)); + + if (waloff[SLIME]) + movelava((char *) waloff[SLIME]); + } + + + i = pp->cursectnum; + + show2dsector[i>>3] |= (1<<(i&7)); + wal = &wall[sector[i].wallptr]; + for (j=sector[i].wallnum; j>0; j--,wal++) + { + i = wal->nextsector; + if (i < 0) continue; + if (wal->cstat&0x0071) continue; + if (wall[wal->nextwall].cstat&0x0071) continue; + if (sector[i].lotag == 32767) continue; + if (sector[i].ceilingz >= sector[i].floorz) continue; + show2dsector[i>>3] |= (1<<(i&7)); + } + + if ((dimensionmode == 5 || dimensionmode == 6) && pp == Player+myconnectindex) + { + VOID MoveScrollMode2D(PLAYERp pp); + extern BOOL ScrollMode2D; + + if (ScrollMode2D) + { + tx = Follow_posx; + ty = Follow_posy; + } + + for (j = 0; j < MAXSPRITES; j++) + { + // Don't show sprites tagged with 257 + if (sprite[j].lotag == 257) + { + if (TEST(sprite[j].cstat, CSTAT_SPRITE_FLOOR)) + { + RESET(sprite[j].cstat, CSTAT_SPRITE_FLOOR); + sprite[j].owner = -2; + } + } + } + + if (dimensionmode == 6) + { + clearview(0L); + drawmapview(tx, ty, zoom, tang); + } + + // Draw the line map on top of texture 2d map or just stand alone + drawoverheadmap(tx, ty, zoom, tang); + } + + for (j = 0; j < MAXSPRITES; j++) + { + // Don't show sprites tagged with 257 + if (sprite[j].lotag == 257 && sprite[j].owner == -2) + SET(sprite[j].cstat, CSTAT_SPRITE_FLOOR); + } + + // if doing a screen save don't need to process the rest + if (ScreenSavePic) + { + DrawScreen = FALSE; + return; + } + + PrintLocationInfo(pp); + PrintSpriteInfo(pp); + +#if SYNC_TEST + SyncStatMessage(); +#endif + + DrawCrosshair(pp); + + + operatefta(); // Draw all the user quotes in the quote array + + operateconfta(); // Draw messages in the console + + DoPlayerDiveMeter(pp); // Do the underwater breathing bar + + // Boss Health Meter, if Boss present + BossHealthMeter(); + + if (ConInputMode) + { + DrawConInput(pp); // Console panel input mode + } + else + DrawMessageInput(pp); // This is only used for non-multiplayer input now + + DrawCompass(pp); + UpdateMiniBar(pp); + + if (UsingMenus) + MNU_DrawMenu(); + else + SecretInfo(pp); + + nextpage(); + +#if SYNC_TEST + SyncStatMessage(); +#endif + + // certain input is done here - probably shouldn't be + DrawCheckKeys(pp); + + restoreinterpolations(); // Stick at end of drawscreen + short_restoreinterpolations(); // Stick at end of drawscreen + + PostDraw(); + DrawScreen = FALSE; +} + +VOID +DrawCompass(PLAYERp pp) +{ +#define COMPASS_TIC 2380 +#define COMPASS_TIC2 2381 + +#define COMPASS_NORTH 2382 +#define COMPASS_NORTH2 2383 + +#define COMPASS_SOUTH 2384 +#define COMPASS_SOUTH2 2385 + +#define COMPASS_EAST 2386 +#define COMPASS_EAST2 2387 + +#define COMPASS_WEST 2388 +#define COMPASS_WEST2 2389 + +#define COMPASS_MID_TIC 2390 +#define COMPASS_MID_TIC2 2391 + +#define COMPASS_X 140 +#define COMPASS_Y (162-5) + +#define NORM_CANG(ang) (((ang) + 32) & 31) + + short start_ang,ang; + short x_size = tilesizx[COMPASS_NORTH]; + short x; + short i; + int flags; + PANEL_SPRITEp psp; + + static short CompassPic[32] = + { + COMPASS_EAST, COMPASS_EAST2, + COMPASS_TIC, COMPASS_TIC2, + COMPASS_MID_TIC, COMPASS_MID_TIC2, + COMPASS_TIC, COMPASS_TIC2, + + COMPASS_SOUTH, COMPASS_SOUTH2, + COMPASS_TIC, COMPASS_TIC2, + COMPASS_MID_TIC, COMPASS_MID_TIC2, + COMPASS_TIC, COMPASS_TIC2, + + COMPASS_WEST, COMPASS_WEST2, + COMPASS_TIC, COMPASS_TIC2, + COMPASS_MID_TIC, COMPASS_MID_TIC2, + COMPASS_TIC, COMPASS_TIC2, + + COMPASS_NORTH, COMPASS_NORTH2, + COMPASS_TIC, COMPASS_TIC2, + COMPASS_MID_TIC, COMPASS_MID_TIC2, + COMPASS_TIC, COMPASS_TIC2, + }; + + static short CompassShade[10] = + { + //20, 16, 11, 6, 1, 1, 6, 11, 16, 20 + 25, 19, 15, 9, 1, 1, 9, 15, 19, 25 + }; + + extern BOOL PanelUpdateMode; + + if (!PanelUpdateMode) + return; + + if (gs.BorderNum < BORDER_BAR || pp - Player != screenpeek) + return; + + ang = pp->pang; + + if (pp->sop_remote) + ang = 0; + + start_ang = (ang + 32) >> 6; + + start_ang = NORM_CANG(start_ang - 4); + + flags = ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER; + if (RedrawCompass) + { + RedrawCompass = FALSE; + SET(flags, ROTATE_SPRITE_ALL_PAGES); + } + + for (i = 0, x = COMPASS_X; i < 10; i++) + { + rotatesprite(x << 16, COMPASS_Y << 16, (1 << 16), 0, + CompassPic[NORM_CANG(start_ang + i)], CompassShade[i], 0, + flags, 0, 0, xdim - 1, ydim - 1); + x += x_size; + } +} + + +VOID ScreenTileLock(void) +{ + walock[SAVE_SCREEN_TILE] = CACHE_LOCK_MAX; +} + +VOID ScreenTileUnLock(void) +{ + walock[SAVE_SCREEN_TILE] = CACHE_UNLOCK_MAX; +} + +int +ScreenLoadSaveSetup(PLAYERp pp) +{ + int tx, ty, tz,thoriz,pp_siz; + short tang,tsectnum; + short i; + + // lock and allocate memory + + ScreenTileLock(); + + if (!waloff[SAVE_SCREEN_TILE]) + allocache((void **)&waloff[SAVE_SCREEN_TILE], SAVE_SCREEN_XSIZE * SAVE_SCREEN_YSIZE, &walock[SAVE_SCREEN_TILE]); + + tilesizx[SAVE_SCREEN_TILE] = SAVE_SCREEN_XSIZE; + tilesizx[SAVE_SCREEN_TILE] = SAVE_SCREEN_YSIZE; + + return SAVE_SCREEN_TILE; +} + +int +ScreenSaveSetup(PLAYERp pp) +{ + short i; + + ScreenLoadSaveSetup(Player + myconnectindex); + + setviewtotile(SAVE_SCREEN_TILE, SAVE_SCREEN_YSIZE, SAVE_SCREEN_XSIZE); + + ScreenSavePic = TRUE; + drawscreen(Player + myconnectindex); + ScreenSavePic = FALSE; + + setviewback(); + + return SAVE_SCREEN_TILE; +} + + + + diff --git a/polymer/eduke32/source/sw/src/eel.c b/polymer/eduke32/source/sw/src/eel.c new file mode 100644 index 000000000..49afd3c08 --- /dev/null +++ b/polymer/eduke32/source/sw/src/eel.c @@ -0,0 +1,682 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- +#include "build.h" + +#include "keys.h" +#include "names2.h" +#include "game.h" +#include "tags.h" +#include "ai.h" +#include "actor.h" +#include "weapon.h" +#include "track.h" + + +DECISION EelBattle[] = +{ + {649, InitActorMoveCloser }, + {650, InitActorAlertNoise }, + {1024, InitActorMoveCloser } +}; + +DECISION EelOffense[] = +{ + {649, InitActorMoveCloser }, + {750, InitActorAlertNoise }, + {1024, InitActorMoveCloser } +}; + +DECISION EelBroadcast[] = +{ + {3, InitActorAlertNoise }, + {6, InitActorAmbientNoise }, + {1024, InitActorDecide } +}; + +DECISION EelSurprised[] = +{ + {701, InitActorMoveCloser }, + {1024, InitActorDecide } +}; + +DECISION EelEvasive[] = +{ + { 790, InitActorRunAway }, + {1024, InitActorMoveCloser }, +}; + +DECISION EelLostTarget[] = +{ + {900, InitActorFindPlayer }, + {1024, InitActorWanderAround } +}; + +DECISION EelCloseRange[] = +{ + {950, InitActorAttack }, + {1024, InitActorReposition } +}; + +ANIMATOR InitEelFire; + +DECISION EelTouchTarget[] = +{ + {1024, InitActorAttack }, +}; + +PERSONALITY EelPersonality = +{ + EelBattle, + EelOffense, + EelBroadcast, + EelSurprised, + EelEvasive, + EelLostTarget, + EelCloseRange, + EelTouchTarget +}; + +ATTRIBUTE EelAttrib = +{ + {100, 110, 120, 130}, // Speeds + {3, 0, -2, -3}, // Tic Adjusts + 3, // MaxWeapons; + { + 0, 0, 0, + 0, 0, 0, + 0,0,0,0 + } +}; + +////////////////////// +// EEL RUN +////////////////////// + +#define EEL_RUN_RATE 20 + +ANIMATOR DoEelMove,NullAnimator,DoStayOnFloor, DoActorDebris, NullEel; + +STATE s_EelRun[5][4] = +{ + { + {EEL_RUN_R0 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][1]}, + {EEL_RUN_R0 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][2]}, + {EEL_RUN_R0 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][3]}, + {EEL_RUN_R0 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][0]}, + }, + { + {EEL_RUN_R1 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][1]}, + {EEL_RUN_R1 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][2]}, + {EEL_RUN_R1 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][3]}, + {EEL_RUN_R1 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][0]}, + }, + { + {EEL_RUN_R2 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][1]}, + {EEL_RUN_R2 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][2]}, + {EEL_RUN_R2 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][3]}, + {EEL_RUN_R2 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][0]}, + }, + { + {EEL_RUN_R3 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][1]}, + {EEL_RUN_R3 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][2]}, + {EEL_RUN_R3 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][3]}, + {EEL_RUN_R3 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][0]}, + }, + { + {EEL_RUN_R4 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][1]}, + {EEL_RUN_R4 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][2]}, + {EEL_RUN_R4 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][3]}, + {EEL_RUN_R4 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][0]}, + } +}; + +STATEp sg_EelRun[] = +{ + &s_EelRun[0][0], + &s_EelRun[1][0], + &s_EelRun[2][0], + &s_EelRun[3][0], + &s_EelRun[4][0] +}; + +////////////////////// +// +// EEL STAND +// +////////////////////// + + +STATE s_EelStand[5][1] = +{ + { + {EEL_RUN_R0 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[0][0]}, + }, + { + {EEL_RUN_R1 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[1][0]}, + }, + { + {EEL_RUN_R2 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[2][0]}, + }, + { + {EEL_RUN_R3 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[3][0]}, + }, + { + {EEL_RUN_R4 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[4][0]}, + } +}; + +STATEp sg_EelStand[] = +{ + &s_EelStand[0][0], + &s_EelStand[1][0], + &s_EelStand[2][0], + &s_EelStand[3][0], + &s_EelStand[4][0] +}; + +////////////////////// +// +// EEL FIRE +// +////////////////////// + +ANIMATOR InitEelFire, EelShock; +#define EEL_FIRE_RATE 12 + +STATE s_EelAttack[5][7] = +{ + { + {EEL_FIRE_R0 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[0][1]}, + {EEL_FIRE_R0 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[0][2]}, + {EEL_FIRE_R0 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[0][3]}, + {EEL_FIRE_R0 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[0][4]}, + {EEL_FIRE_R0 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[0][5]}, + {EEL_FIRE_R0 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[0][6]}, + {EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[0][6]} + }, + { + {EEL_FIRE_R1 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[1][1]}, + {EEL_FIRE_R1 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[1][2]}, + {EEL_FIRE_R1 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[1][3]}, + {EEL_FIRE_R1 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[1][5]}, + {EEL_FIRE_R1 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[1][6]}, + {EEL_FIRE_R1 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[1][7]}, + {EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[1][7]} + }, + { + {EEL_FIRE_R2 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[2][1]}, + {EEL_FIRE_R2 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[2][2]}, + {EEL_FIRE_R2 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[2][3]}, + {EEL_FIRE_R2 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[2][4]}, + {EEL_FIRE_R2 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[2][5]}, + {EEL_FIRE_R2 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[2][6]}, + {EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[2][6]} + }, + { + {EEL_RUN_R3 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[3][1]}, + {EEL_RUN_R3 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[3][2]}, + {EEL_RUN_R3 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[3][3]}, + {EEL_RUN_R3 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[3][4]}, + {EEL_RUN_R3 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[3][5]}, + {EEL_RUN_R3 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[3][6]}, + {EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[3][6]} + }, + { + {EEL_RUN_R4 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[4][1]}, + {EEL_RUN_R4 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[4][2]}, + {EEL_RUN_R4 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[4][3]}, + {EEL_RUN_R4 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[4][4]}, + {EEL_RUN_R4 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[4][5]}, + {EEL_RUN_R4 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[4][6]}, + {EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[4][6]} + } +}; + +STATEp sg_EelAttack[] = +{ + &s_EelAttack[0][0], + &s_EelAttack[1][0], + &s_EelAttack[2][0], + &s_EelAttack[3][0], + &s_EelAttack[4][0] +}; + + +////////////////////// +// +// EEL DIE +// +////////////////////// + +#define EEL_DIE_RATE 20 + +ANIMATOR DoEelDeath; +STATE s_EelDie[] = +{ + {EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[1]}, + {EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[2]}, + {EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[3]}, + {EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[4]}, + {EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[5]}, + {EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[5]}, +}; + +STATEp sg_EelDie[] = +{ + s_EelDie +}; + +STATE s_EelDead[] = +{ +// {EEL_DEAD, SF_QUICK_CALL , QueueFloorBlood, &s_EelDead[1]}, + {EEL_DEAD, EEL_DIE_RATE, DoActorDebris, &s_EelDead[0]}, +}; + +STATEp sg_EelDead[] = +{ + s_EelDead +}; + + +/* +STATEp *Stand[MAX_WEAPONS]; +STATEp *Run; +STATEp *Jump; +STATEp *Fall; +STATEp *Crawl; +STATEp *Swim; +STATEp *Fly; +STATEp *Rise; +STATEp *Sit; +STATEp *Look; +STATEp *Climb; +STATEp *Pain; +STATEp *Death1; +STATEp *Death2; +STATEp *Dead; +STATEp *DeathJump; +STATEp *DeathFall; +STATEp *CloseAttack[2]; +STATEp *Attack[6]; +STATEp *Special[2]; +*/ + + +ACTOR_ACTION_SET EelActionSet = +{ + sg_EelStand, + sg_EelRun, + NULL, + NULL, + NULL, + sg_EelRun, + NULL, + NULL, + sg_EelStand, + NULL, + NULL, //climb + sg_EelStand, //pain + sg_EelDie, + NULL, + sg_EelDead, + NULL, + NULL, + {sg_EelAttack}, + {1024}, + {sg_EelAttack}, + {1024}, + {NULL,NULL}, + NULL, + NULL +}; + +int DoEelMatchPlayerZ(short SpriteNum); + + +void +EelCommon(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + sp->clipdist = (100) >> 2; + u->floor_dist = Z(16); + u->floor_dist = Z(16); + u->ceiling_dist = Z(20); + + u->sz = sp->z; + + sp->xrepeat = 35; + sp->yrepeat = 27; + u->Radius = 400; +} + +int +SetupEel(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u; + ANIMATOR DoActorDecide; + + if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE)) + { + u = User[SpriteNum]; + ASSERT(u); + } + else + { + User[SpriteNum] = u = SpawnUser(SpriteNum,EEL_RUN_R0,s_EelRun[0]); + u->Health = 40; + } + + ChangeState(SpriteNum, s_EelRun[0]); + u->Attrib = &EelAttrib; + DoActorSetSpeed(SpriteNum, NORM_SPEED); + u->StateEnd = s_EelDie; + u->Rot = sg_EelRun; + + EnemyDefaults(SpriteNum, &EelActionSet, &EelPersonality); + + SET(u->Flags, SPR_NO_SCAREDZ|SPR_XFLIP_TOGGLE); + + EelCommon(SpriteNum); + + RESET(u->Flags, SPR_SHADOW); // Turn off shadows + u->zclip = Z(8); + + return 0; +} + +#if 0 +int +NewEel(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + USERp nu; + SPRITEp np; + ANIMATOR DoActorDecide; + short new; + + + new = SpawnSprite(STAT_ENEMY, EEL_RUN_R0, &s_EelBirth, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 50); + + nu = User[new]; + np = &sprite[new]; + + ChangeState(new, &s_EelBirth); + nu->StateEnd = s_EelDie; + nu->Rot = sg_EelRun; + np->pal = nu->spal = u->spal; + + nu->ActorActionSet = &EelActionSet; + + np->shade = sp->shade; + + EelCommon(new); + + return 0; +} +#endif + +int NullEel(short SpriteNum) +{ + USERp u = User[SpriteNum]; + SPRITEp sp = User[SpriteNum]->SpriteP; + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + DoEelMatchPlayerZ(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + return 0; +} + +int DoEelMatchPlayerZ(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + SPRITEp tsp = User[SpriteNum]->tgt_sp; + int zdiff,zdist; + int loz,hiz; + int dist,a,b,c; + + int bound; + + if (FAF_ConnectArea(sp->sectnum)) + { + if (u->hi_sectp) + { + u->hiz = sector[sp->sectnum].ceilingz + Z(16); + u->hi_sectp = §or[sp->sectnum]; + } + else + { + if (u->hiz < sector[sp->sectnum].ceilingz + Z(16)) + u->hiz = sector[sp->sectnum].ceilingz + Z(16); + } + } + + // actor does a sine wave about u->sz - this is the z mid point + + zdiff = (SPRITEp_BOS(tsp) - Z(8)) - u->sz; + + // check z diff of the player and the sprite + zdist = Z(20 + RANDOM_RANGE(64)); // put a random amount + if (labs(zdiff) > zdist) + { + if (zdiff > 0) + // manipulate the z midpoint + u->sz += 160 * ACTORMOVETICS; + else + u->sz -= 160 * ACTORMOVETICS; + } + +#define EEL_BOB_AMT (Z(4)) + + // save off lo and hi z + loz = u->loz; + hiz = u->hiz; + + // adjust loz/hiz for water depth + if (u->lo_sectp && SectUser[u->lo_sectp - sector] && SectUser[u->lo_sectp - sector]->depth) + loz -= Z(SectUser[u->lo_sectp - sector]->depth) - Z(8); + + // lower bound + if (u->lo_sp && u->tgt_sp == u->hi_sp) + { + DISTANCE(sp->x, sp->y, u->lo_sp->x, u->lo_sp->y, dist, a, b, c); + if (dist <= 300) + bound = u->sz; + else + bound = loz - u->floor_dist; + } + else + bound = loz - u->floor_dist - EEL_BOB_AMT; + + if (u->sz > bound) + { + u->sz = bound; + } + + // upper bound + if (u->hi_sp && u->tgt_sp == u->hi_sp) + { + DISTANCE(sp->x, sp->y, u->hi_sp->x, u->hi_sp->y, dist, a, b, c); + if (dist <= 300) + bound = u->sz; + else + bound = hiz + u->ceiling_dist; + } + else + bound = hiz + u->ceiling_dist + EEL_BOB_AMT; + + if (u->sz < bound) + { + u->sz = bound; + } + + u->sz = min(u->sz, loz - u->floor_dist); + u->sz = max(u->sz, hiz + u->ceiling_dist); + + u->Counter = (u->Counter + (ACTORMOVETICS << 3) + (ACTORMOVETICS << 1)) & 2047; + sp->z = u->sz + ((EEL_BOB_AMT * (int)sintable[u->Counter]) >> 14); + + bound = u->hiz + u->ceiling_dist + EEL_BOB_AMT; + if (sp->z < bound) + { + // bumped something + sp->z = u->sz = bound + EEL_BOB_AMT; + } + + return 0; +} + +int +DoEelDeath(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + int nx, ny; + if (TEST(u->Flags, SPR_FALLING)) + { + DoFall(SpriteNum); + } + else + { + DoFindGroundPoint(SpriteNum); + u->floor_dist = 0; + DoBeginFall(SpriteNum); + } + + if (TEST(u->Flags, SPR_SLIDING)) + DoActorSlide(SpriteNum); + + // slide while falling + nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14; + ny = sp->xvel * (int) sintable[sp->ang] >> 14; + + u->ret = move_sprite(SpriteNum, nx, ny, 0L, u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, ACTORMOVETICS); + DoFindGroundPoint(SpriteNum); + + // on the ground + if (sp->z >= u->loz) + { + RESET(u->Flags, SPR_FALLING|SPR_SLIDING); + if (RANDOM_RANGE(1000) > 500) + SET(sp->cstat, CSTAT_SPRITE_XFLIP); + if (RANDOM_RANGE(1000) > 500) + SET(sp->cstat, CSTAT_SPRITE_YFLIP); + NewStateGroup(SpriteNum, u->ActorActionSet->Dead); + return 0; + } + + return 0; +} + +int DoEelMove(short SpriteNum) +{ + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; + + ASSERT(u->Rot != NULL); + + if (SpriteOverlap(SpriteNum, u->tgt_sp - sprite)) + NewStateGroup(SpriteNum, u->ActorActionSet->CloseAttack[0]); + + if (TEST(u->Flags,SPR_SLIDING)) + DoActorSlide(SpriteNum); + + if (u->track >= 0) + ActorFollowTrack(SpriteNum, ACTORMOVETICS); + else + (*u->ActorActionFunc)(SpriteNum); + + //if (TEST_SYNC_KEY((Player+myconnectindex), SK_OPERATE)) + // CON_Message("Stop"); + + DoEelMatchPlayerZ(SpriteNum); + + DoActorSectorDamage(SpriteNum); + + return 0; + +} + + +#include "saveable.h" + +static saveable_code saveable_eel_code[] = +{ + SAVE_CODE(EelCommon), + SAVE_CODE(SetupEel), + //SAVE_CODE(NewEel), + SAVE_CODE(DoEelMatchPlayerZ), + SAVE_CODE(DoEelDeath), + SAVE_CODE(DoEelMove) +}; + +static saveable_data saveable_eel_data[] = +{ + SAVE_DATA(EelBattle), + SAVE_DATA(EelOffense), + SAVE_DATA(EelBroadcast), + SAVE_DATA(EelSurprised), + SAVE_DATA(EelEvasive), + SAVE_DATA(EelLostTarget), + SAVE_DATA(EelCloseRange), + SAVE_DATA(EelTouchTarget), + + SAVE_DATA(EelPersonality), + + SAVE_DATA(EelAttrib), + + SAVE_DATA(s_EelRun), + SAVE_DATA(sg_EelRun), + SAVE_DATA(s_EelStand), + SAVE_DATA(sg_EelStand), + SAVE_DATA(s_EelAttack), + SAVE_DATA(sg_EelAttack), + SAVE_DATA(s_EelDie), + SAVE_DATA(sg_EelDie), + SAVE_DATA(s_EelDead), + SAVE_DATA(sg_EelDead), + + SAVE_DATA(EelActionSet) +}; + +saveable_module saveable_eel = +{ + // code + saveable_eel_code, + SIZ(saveable_eel_code), + + // data + saveable_eel_data, + SIZ(saveable_eel_data) +}; diff --git a/polymer/eduke32/source/sw/src/function.h b/polymer/eduke32/source/sw/src/function.h new file mode 100644 index 000000000..1ee57a2a8 --- /dev/null +++ b/polymer/eduke32/source/sw/src/function.h @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +// function.h + +// file created by makehead.exe +// these headers contain default key assignments, as well as +// default button assignments and game function names +// axis defaults are also included + + +#ifndef function_public_ +#define function_public_ + +#define NUMGAMEFUNCTIONS 51 + +extern char *gamefunctions[]; + +enum +{ + gamefunc_Move_Forward, + gamefunc_Move_Backward, + gamefunc_Turn_Left, + gamefunc_Turn_Right, + gamefunc_Strafe, + gamefunc_Fire, + gamefunc_Open, + gamefunc_Run, + gamefunc_AutoRun, + gamefunc_Jump, + gamefunc_Crouch, + gamefunc_Look_Up, + gamefunc_Look_Down, + gamefunc_Strafe_Left, + gamefunc_Strafe_Right, + gamefunc_Aim_Up, + gamefunc_Aim_Down, + gamefunc_Weapon_1, + gamefunc_Weapon_2, + gamefunc_Weapon_3, + gamefunc_Weapon_4, + gamefunc_Weapon_5, + gamefunc_Weapon_6, + gamefunc_Weapon_7, + gamefunc_Weapon_8, + gamefunc_Weapon_9, + gamefunc_Weapon_10, + gamefunc_Inventory, + gamefunc_Inventory_Left, + gamefunc_Inventory_Right, + gamefunc_Med_Kit, + gamefunc_Smoke_Bomb, + gamefunc_Night_Vision, + gamefunc_Gas_Bomb, + gamefunc_Flash_Bomb, + gamefunc_Caltrops, + gamefunc_TurnAround, + gamefunc_SendMessage, + gamefunc_Map, + gamefunc_Shrink_Screen, + gamefunc_Enlarge_Screen, + gamefunc_Center_View, + gamefunc_Holster_Weapon, + gamefunc_Map_Follow_Mode, + gamefunc_See_Co_Op_View, + gamefunc_Mouse_Aiming, + gamefunc_Toggle_Crosshair, + gamefunc_Next_Weapon, + gamefunc_Previous_Weapon, + gamefunc_Show_Menu, + gamefunc_Show_Console, +}; +#endif diff --git a/polymer/eduke32/source/sw/src/game.c b/polymer/eduke32/source/sw/src/game.c new file mode 100644 index 000000000..648bec012 --- /dev/null +++ b/polymer/eduke32/source/sw/src/game.c @@ -0,0 +1,6004 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +// CTW NOTE +/* +Known remaining issues: +- Audio stuttering. +- CD Audio not looping properly (currently hard coded to restart about every 200 seconds. +- Hitting F5 to change resolution causes a crash (currently disabled). +- Multiplayer untested. + +Things required to make savegames work: +- Load makesym.wpj and build it. +- In a DOS prompt, run "makesym sw.map swdata.map swcode.map" +- Copy swcode.map to swcode.sym and swdata.map to swdata.sym +*/ +// CTW NOTE END + +#define MAIN +#define QUIET +#include "build.h" +#include "baselayer.h" +#include "cache1d.h" +#include "osd.h" +#ifdef RENDERTYPEWIN +# include "winlayer.h" +#endif + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "tags.h" +#include "sector.h" +#include "sprite.h" +#include "weapon.h" +#include "player.h" +#include "lists.h" +#include "net.h" +#include "pal.h" +#include "fx_man.h" + +#include "mytypes.h" +//#include "config.h" + +#include "menus.h" + +#include "control.h" +#include "function.h" +#include "gamedefs.h" +#include "config.h" + +#include "demo.h" +#include "cache.h" +//#include "exports.h" + +#include "anim.h" + +#include "colormap.h" +#include "break.h" +#include "ninja.h" +#include "light.h" +#include "track.h" +#include "jsector.h" +#include "keyboard.h" +#include "text.h" +#include "music.h" + +#include "crc32.h" + +#if DEBUG +#define BETA 0 +#endif + +#define STAT_SCREEN_PIC 5114 +#define TITLE_PIC 2324 +#define THREED_REALMS_PIC 2325 +#define TITLE_ROT_FLAGS (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK) +#define PAL_SIZE (256*3) + +char DemoName[15][16]; + +// Stupid WallMart version! +//#define PLOCK_VERSION TRUE + +#if PLOCK_VERSION +BOOL Global_PLock = TRUE; +#else +BOOL Global_PLock = FALSE; +#endif + +int GameVersion = 13; // 12 was original source release. For future releases increment by two. +char DemoText[3][64]; +int DemoTextYstart = 0; + +BOOL DoubleInitAWE32 = FALSE; +int Follow_posx=0,Follow_posy=0; + +BOOL NoMeters = FALSE; +short IntroAnimCount = 0; +short PlayingLevel = -1; +BOOL GraphicsMode = FALSE; +char CacheLastLevel[32] = ""; +char PlayerNameArg[32] = ""; +BOOL CleanExit = FALSE; +extern char cachedebug; +BOOL DemoModeMenuInit = FALSE; +BOOL FinishAnim = 0; +BOOL CachePrintMode = FALSE; +BOOL ShortGameMode = FALSE; +BOOL ReloadPrompt = FALSE; +BOOL ReloadPromptMode = FALSE; +BOOL NewGame = TRUE; +BOOL InMenuLevel = FALSE; +BOOL LoadGameOutsideMoveLoop = FALSE; +BOOL LoadGameFromDemo = FALSE; +BOOL ArgCheat = FALSE; +extern BOOL NetBroadcastMode, NetModeOverride; +BOOL MultiPlayQuitFlag = FALSE; +//Miscellaneous variables +char MessageInputString[256]; +char MessageOutputString[256]; +BOOL MessageInputMode = FALSE; +BOOL ConInputMode = FALSE; +BOOL ConPanel = FALSE; +BOOL FinishedLevel = FALSE; +BOOL HelpInputMode = FALSE; +BOOL PanelUpdateMode = TRUE; +short HelpPage = 0; +short HelpPagePic[] = { 5115, 5116, 5117 }; +BOOL InputMode = FALSE; +BOOL MessageInput = FALSE; +extern BOOL GamePaused; +short screenpeek = 0; +BOOL NoDemoStartup = FALSE; +BOOL FirstTimeIntoGame; +extern BYTE RedBookSong[40]; + +BOOL BorderAdjust = TRUE; +BOOL LocationInfo = 0; +VOID drawoverheadmap(int cposx, int cposy, int czoom, short cang); +int DispFrameRate = FALSE; +int DispMono = TRUE; +int Fog = FALSE; +int FogColor; +int PreCaching = TRUE; +int GodMode = FALSE; +int BotMode = FALSE; +short Skill = 2; +short BetaVersion = 900; +short TotalKillable; + +AUTO_NET Auto; +BOOL AutoNet = FALSE; +BOOL HasAutoColor = FALSE; +BYTE AutoColor; + +const GAME_SET gs_defaults = +{ + 32768, // mouse speed + 128, // music vol + 192, // fx vol + 2, // border + 0, // brightness + 0, // border tile + FALSE, // mouse aiming + FALSE, // mouse look + FALSE, // mouse invert + TRUE, // bobbing + FALSE, // tilting + TRUE, // shadows + FALSE, // auto run + TRUE, // crosshair + TRUE, // auto aim + TRUE, // messages + TRUE, // fx on + TRUE, // Music on + TRUE, // talking + TRUE, // ambient + FALSE, // Flip Stereo + +// Network game settings + 0, // GameType + 0, // Level + 0, // Monsters + FALSE, // HurtTeammate + TRUE, // SpawnMarkers Markers + FALSE, // TeamPlay + 0, // Kill Limit + 0, // Time Limit + 0, // Color + 0, // Parental Lock + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", // Password + TRUE, // nuke + TRUE, // voxels + FALSE, // stats + FALSE, // mouse aiming on + FALSE, // play cd + "track??.ogg", // ogg track name +}; +GAME_SET gs; + +char PlaxBits = 0; +BOOL PlayerTrackingMode = FALSE; +BOOL PauseMode = FALSE; +BOOL PauseKeySet = FALSE; +BOOL SlowMode = FALSE; +BOOL FrameAdvanceTics = 3; +BOOL ScrollMode2D = FALSE; + +BOOL DebugSO = FALSE; +BOOL DebugPanel = FALSE; +BOOL DebugSector = FALSE; +BOOL DebugActor = FALSE; +BOOL DebugAnim = FALSE; +BOOL DebugOperate = FALSE; +BOOL DebugActorFreeze = FALSE; +VOID LoadingLevelScreen(char *level_name); + +BYTE FakeMultiNumPlayers; + +int totalsynctics; +int turn_scale = 256; +int move_scale = 256; + +short Level = 0; +BOOL ExitLevel = FALSE; +SHORT OrigCommPlayers=0; +extern BYTE CommPlayers; +extern BOOL CommEnabled; +extern int bufferjitter; + +BOOL CameraTestMode = FALSE; + +char ds[256]; // debug string + +extern short NormalVisibility; + +extern int quotebot, quotebotgoal; // Multiplayer typing buffer +char recbuf[80]; // Used as a temp buffer to hold typing text + +extern unsigned char palette_data[256][3]; // Global palette array + +#define ACT_STATUE 0 + +int score; +BOOL QuitFlag = FALSE; +BOOL InGame = FALSE; + +BOOL CommandSetup = FALSE; + +char UserMapName[80]="", buffer[80], ch; +char LevelName[20]; + +BYTE DebugPrintColor = 255; + +int krandcount; + +/// L O C A L P R O T O T Y P E S ///////////////////////////////////////////////////////// +void BOT_DeleteAllBots(void); +VOID BotPlayerInsert(PLAYERp pp); +VOID SybexScreen(VOID); +VOID DosScreen(VOID); +VOID MenuLevel(VOID); +VOID StatScreen(PLAYERp mpp); +VOID InitRunLevel(VOID); +VOID RunLevel(VOID); +///////////////////////////////////////////////////////////////////////////////////////////// + +static FILE *debug_fout = NULL; + +VOID DebugWriteString(char *string) +{ + +#if BETA || !DEBUG + return; +#endif + + if (!debug_fout) + { + if ((debug_fout = fopen("dbg.foo", "ab+")) == NULL) + return; + } + + fprintf(debug_fout, "%s\n", string); + + //fclose(debug_fout); + //debug_fout = NULL; + + fflush(debug_fout); +} + +VOID DebugWriteLoc(char *fname, int line) +{ + +#if BETA || !DEBUG + return; +#endif + + if (!debug_fout) + { + if ((debug_fout = fopen("dbg.foo", "ab+")) == NULL) + return; + } + + fprintf(debug_fout, "%s, %d\n", fname, line); + + //fclose(debug_fout); + //debug_fout = NULL; + + fflush(debug_fout); +} + +void Mono_Print(char *str) +{ + MONO_PRINT(str); +} + + +extern BOOL DrawScreen; +#if RANDOM_DEBUG +FILE *fout_err; +BOOL RandomPrint; +int krand1(char *file, unsigned line) +{ + ASSERT(!DrawScreen); + if (RandomPrint && !Prediction) + { + extern ULONG MoveThingsCount; + sprintf(ds,"mtc %d, %s, line %d, %d",MoveThingsCount,file,line,randomseed); + DebugWriteString(ds); + } + randomseed = ((randomseed * 21 + 1) & 65535); + return randomseed; +} + +int krand2() +{ + ASSERT(!DrawScreen); + randomseed = ((randomseed * 21 + 1) & 65535); + return randomseed; +} + +#else +int krand1(void) +{ + ASSERT(!DrawScreen); + krandcount++; + randomseed = ((randomseed * 21 + 1) & 65535); + return randomseed; +} + +#endif + +VOID * +CacheAlloc(void **ptr, int size, unsigned char *lock_byte) +{ + if (*ptr == NULL) + { + *lock_byte = CACHE_LOCK_START; + allocache(ptr, size, lock_byte); + } + else + { + if (*lock_byte < CACHE_LOCK_START) + *lock_byte = CACHE_LOCK_START; + else + (*lock_byte)++; + } + + return *ptr; +} + +VOID +CacheFree(void **ptr, unsigned char *lock_byte) +{ + if (*ptr == NULL) + { + ASSERT(*lock_byte == NULL); + } + else + { + if (*lock_byte < CACHE_LOCK_START) + *lock_byte = CACHE_UNLOCK_START; + } +} + +/* +void HeapCheck(char *file, int line) +{ + switch( _heapchk() ) + { + case _HEAPOK: + //printf( "OK - heap is good\n" ); + break; + case _HEAPEMPTY: + //printf( "OK - heap is empty\n" ); + break; + case _HEAPBADBEGIN: + sprintf(ds, "ERROR - heap is damaged: %s, %d", file, line); + MONO_PRINT(ds); + DebugWriteString(ds); + setvmode(0x3); + printf( "%s\n", ds); + exit(0); + break; + case _HEAPBADNODE: + sprintf(ds, "ERROR - bad node in heap: %s, %d", file, line); + MONO_PRINT(ds); + DebugWriteString(ds); + setvmode(0x3); + printf( "%s\n", ds); + exit(0); + break; + } +} + */ + +#if DEBUG +BOOL +ValidPtr(VOID *ptr) +{ + MEM_HDRp mhp; + BYTEp check; + + ASSERT(ptr != NULL); + + mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR)); + + if (mhp->size == 0 || mhp->checksum == 0) + { + printf("ValidPtr(): Size or Checksum == 0!\n"); + return FALSE; + } + + check = (BYTEp) & mhp->size; + + if (mhp->checksum == check[0] + check[1] + check[2] + check[3]) + return TRUE; + + printf("ValidPtr(): Checksum bad!\n"); + return FALSE; +} + +VOID +PtrCheckSum(VOID *ptr, unsigned int *stored, unsigned int *actual) +{ + MEM_HDRp mhp; + BYTEp check; + + ASSERT(ptr != NULL); + + mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR)); + + check = (BYTEp) & mhp->size; + + *stored = mhp->checksum; + *actual = check[0] + check[1] + check[2] + check[3]; +} + +VOID * +AllocMem(int size) +{ + BYTEp bp; + MEM_HDRp mhp; + BYTEp check; + + ASSERT(size != 0); + + bp = (BYTEp) malloc(size + sizeof(MEM_HDR)); + + // Used for debugging, we can remove this at ship time + if (bp == NULL) + { + TerminateGame(); + printf("Memory could NOT be allocated in AllocMem: size = %d\n",size); + exit(0); + } + + ASSERT(bp != NULL); + + mhp = (MEM_HDRp) bp; + + mhp->size = size; + check = (BYTEp) & mhp->size; + mhp->checksum = check[0] + check[1] + check[2] + check[3]; + + bp += sizeof(MEM_HDR); + + return bp; +} + +VOID * +ReAllocMem(VOID *ptr, int size) +{ + BYTEp bp; + MEM_HDRp mhp; + BYTEp check; + + ASSERT(size != 0); + + ASSERT(ValidPtr(ptr)); + + mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR)); + + bp = (BYTEp) realloc(mhp, size + sizeof(MEM_HDR)); + + ASSERT(bp != NULL); + + mhp = (MEM_HDRp) bp; + + mhp->size = size; + check = (BYTEp) & mhp->size; + mhp->checksum = check[0] + check[1] + check[2] + check[3]; + + bp += sizeof(MEM_HDR); + + ASSERT(ValidPtr(bp)); + + return bp; +} + + +VOID * +CallocMem(int size, int num) +{ + BYTEp bp; + MEM_HDRp mhp; + BYTEp check; + int num_bytes; + + ASSERT(size != 0 && num != 0); + + num_bytes = (size * num) + sizeof(MEM_HDR); + bp = (BYTEp) calloc(num_bytes, 1); + + // Used for debugging, we can remove this at ship time + if (bp == NULL) + { + TerminateGame(); + printf("Memory could NOT be allocated in CallocMem: size = %d, num = %d\n",size,num); + exit(0); + } + + ASSERT(bp != NULL); + + mhp = (MEM_HDRp) bp; + + mhp->size = size; + check = (BYTEp) & mhp->size; + mhp->checksum = check[0] + check[1] + check[2] + check[3]; + + bp += sizeof(MEM_HDR); + + return bp; +} + +VOID +FreeMem(VOID *ptr) +{ + MEM_HDRp mhp; + BYTEp check; + + ASSERT(ptr != NULL); + + ASSERT(ValidPtr(ptr)); + + mhp = (MEM_HDRp)(((BYTEp) ptr) - sizeof(MEM_HDR)); + check = (BYTEp)&mhp->size; + + memset(mhp, 0xCC, mhp->size + sizeof(MEM_HDR)); + + free(mhp); +} + +#else +BOOL +ValidPtr(VOID *ptr) +{ + return TRUE; +} + +VOID * +AllocMem(int size) +{ + return malloc(size); +} + +VOID * +CallocMem(int size, int num) +{ + return calloc(size, num); +} + +VOID * +ReAllocMem(VOID *ptr, int size) +{ + return realloc(ptr, size); +} + +VOID +FreeMem(VOID *ptr) +{ + free(ptr); +} + +#endif + +int PointOnLine(int x, int y, int x1, int y1, int x2, int y2) +{ + // the closer to 0 the closer to the line the point is + return ((x2 - x1) * (y - y1)) - ((y2 - y1) * (x - x1)); +} + +int +Distance(int x1, int y1, int x2, int y2) +{ + int min; + + if ((x2 = x2 - x1) < 0) + x2 = -x2; + + if ((y2 = y2 - y1) < 0) + y2 = -y2; + + if (x2 > y2) + min = y2; + else + min = x2; + + return x2 + y2 - DIV2(min); +} + +VOID +MapSetAll2D(BYTE fill) +{ + int i; + + for (i = 0; i < (MAXWALLS >> 3); i++) + show2dwall[i] = fill; + for (i = 0; i < (MAXSPRITES >> 3); i++) + show2dsprite[i] = fill; + + //for (i = 0; i < (MAXSECTORS >> 3); i++) + for (i = 0; i < MAXSECTORS; i++) + { + if (sector[i].ceilingpicnum != 342 && sector[i].floorpicnum != 342) + show2dsector[i>>3] |= (1<<(i&7)); + //show2dsector[i] = fill; + } +} + +VOID +MapSetup(VOID) +{ +#define NO_AUTO_MAPPING FALSE + +#if NO_AUTO_MAPPING + MapSetAll2D(0xFF); +#else + automapping = TRUE; +#endif +} + +VOID +setup2dscreen(VOID) +{ + // qsetmode640350(); +} + + + +VOID +TerminateGame(VOID) +{ + int i,j; + int oldtotalclock; + + DemoTerm(); + + ErrorCorrectionQuit(); + + uninitmultiplayers(); + + if (CleanExit) + { + SybexScreen(); + //TenScreen(); + } + + ////--->>>> sound stuff was there + //uninitkeys(); + KB_Shutdown(); + + uninitengine(); + TermSetup(); + + //Terminate3DSounds(); // Kill the sounds linked list + UnInitSound(); + + uninittimer(); + + if (CleanExit) + DosScreen(); + + uninitgroupfile(); +} + +VOID +LoadLevel(char *filename) +{ + int pos; + + if (loadboard(filename, SW_SHAREWARE ? 1 : 0, &Player[0].posx, &Player[0].posy, &Player[0].posz, &Player[0].pang, &Player[0].cursectnum) == -1) + { + TerminateGame(); +#ifdef RENDERTYPEWIN + { + char msg[256]; + Bsnprintf(msg, 256, "Level not found: %s", filename); + wm_msgbox(apptitle, msg); + } +#else + printf("Level Not Found: %s\n", filename); +#endif + exit(0); + } +} + +VOID +LoadImages(char *filename) +{ + short ndx; + FILE *fin; + + if (loadpics(filename, 32*1048576) == -1) + { + TerminateGame(); +#ifdef RENDERTYPEWIN + { + wm_msgbox(apptitle, "Art not found. Please check your GRP file."); + } +#else + printf("Art not found. Please check your GRP file.\n"); +#endif + exit(-1); + } +} + +void LoadDemoRun(void) +{ + short i; + FILE *fin; + + fin = fopen("demos.run","r"); + if (fin) + { + memset(DemoName,'\0',sizeof(DemoName)); + for (i = 0; TRUE; i++) + { + if (fscanf(fin, "%s", DemoName[i]) == EOF) + break; + } + + fclose(fin); + } + + memset(DemoText,'\0',sizeof(DemoText)); + fin = fopen("demotxt.run","r"); + if (fin) + { + fgets(ds, 6, fin); + sscanf(ds,"%d",&DemoTextYstart); + for (i = 0; TRUE; i++) + { + if (fgets(DemoText[i], SIZ(DemoText[0])-1, fin) == NULL) + break; + } + + fclose(fin); + } +} + +void DisplayDemoText(void) +{ + short w,h; + short i; + + for (i = 0; i < 3; i++) + { + MNU_MeasureString(DemoText[i], &w, &h); + PutStringTimer(Player, TEXT_TEST_COL(w), DemoTextYstart+(i*12), DemoText[i], 999); + } +} + + +void Set_GameMode(void) +{ + extern int ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP; + int result; + char ch; + + //DSPRINTF(ds,"ScreenMode %d, ScreenWidth %d, ScreenHeight %d",ScreenMode, ScreenWidth, ScreenHeight); + //MONO_PRINT(ds); + result = COVERsetgamemode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP); + + if (result < 0) + { + buildprintf("Failure setting video mode %dx%dx%d %s! Attempting safer mode...", + ScreenWidth,ScreenHeight,ScreenBPP,ScreenMode ? "fullscreen" : "windowed"); + ScreenMode = 0; + ScreenWidth = 640; + ScreenHeight = 480; + ScreenBPP = 8; + + result = COVERsetgamemode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP); + if (result < 0) + { + uninitmultiplayers(); + //uninitkeys(); + KB_Shutdown(); + uninitengine(); + TermSetup(); + UnInitSound(); + uninittimer(); + DosScreen(); + uninitgroupfile(); + exit(0); + } + } +} + +void MultiSharewareCheck(void) +{ + if (!SW_SHAREWARE) return; + if (numplayers > 4) + { +#ifdef RENDERTYPEWIN + wm_msgbox(apptitle,"To play a Network game with more than 4 players you must purchase " + "the full version. Read the Ordering Info screens for details."); +#else + printf( + "\n\nTo play a Network game with more than 4 players you must purchase the\n" + "full version. Read the Ordering Info screens for details.\n\n"); +#endif + uninitmultiplayers(); + //uninitkeys(); + KB_Shutdown(); + uninitengine(); + TermSetup(); + UnInitSound(); + uninittimer(); + uninitgroupfile(); + exit(0); + } +} + + +// Some mem crap for Jim +// I reserve 1 meg of heap space for our use out side the cache +int TotalMemory = 0; +int ActualHeap = 0; + +VOID InitAutoNet(VOID) +{ + if (!AutoNet) + return; + + gs.NetGameType = Auto.Rules; + gs.NetLevel = Auto.Level; + gs.NetMonsters = Auto.Enemy; + gs.NetSpawnMarkers = Auto.Markers; + gs.NetTeamPlay = Auto.Team; + gs.NetHurtTeammate = Auto.HurtTeam; + gs.NetKillLimit = Auto.Kill; + gs.NetTimeLimit = Auto.Time; + gs.NetColor = Auto.Color; + gs.NetNuke = Auto.Nuke; +} + + +void AnimateCacheCursor(void) +{ +#if 0 + struct rccoord old_pos; + static short cursor_num = 0; + static char cache_cursor[] = {'|','/','-','\\'}; + + if (GraphicsMode) + return; + + cursor_num++; + if (cursor_num > 3) + cursor_num = 0; + + //old_pos = _gettextposition(); + //_settextposition( old_pos.row, old_pos.col ); + //_settextposition( 24, 25); + _settextposition(25, 0); + sprintf(ds,"Loading sound and graphics %c", cache_cursor[cursor_num]); + _outtext(ds); + //_settextposition( old_pos.row, old_pos.col ); +#endif +} + +void COVERsetbrightness(int bright, unsigned char *pal) +{ + setbrightness(bright, pal, 0); +} + + +static int firstnet = 0; // JBF +int nextvoxid = 0; // JBF +static const char *deffile = "sw.def"; + +extern int startwin_run(void); + +VOID +InitGame(VOID) +{ + extern int MovesPerPacket; + //void *ReserveMem=NULL; + int i; + + DSPRINTF(ds,"InitGame..."); + MONO_PRINT(ds); + + + if (initengine()) + { + wm_msgbox("Build Engine Initialisation Error", + "There was a problem initialising the Build engine: %s", engineerrstr); + exit(1); + } + + //initgroupfile("sw.grp"); // JBF: moving this close to start of program to detect shareware + InitSetup(); + + InitAutoNet(); + + inittimer(120); + + CON_InitConsole(); // Init console command list + + ////DSPRINTF(ds,"%s, %d",__FILE__,__LINE__); MONO_PRINT(ds); + + //InitFX(); + + memcpy(palette_data,palette,768); + InitPalette(); + // sets numplayers, connecthead, connectpoint2, myconnectindex + + if (!firstnet) + initmultiplayers(0, NULL, 0, 0, 0); + else if (initmultiplayersparms(_buildargc - firstnet, &_buildargv[firstnet])) + { + buildputs("Waiting for players...\n"); + while (initmultiplayerscycle()) + { + handleevents(); + if (quitevent) + { + QuitFlag = TRUE; + return; + } + } + } + initsynccrc(); + + // code to duplicate packets + if (numplayers > 4 && MovesPerPacket == 1) + { + MovesPerPacket = 2; + } + + MultiSharewareCheck(); + + if (numplayers > 1) + { + CommPlayers = numplayers; + OrigCommPlayers = CommPlayers; + CommEnabled = TRUE; + if (!BotMode) + gNet.MultiGameType = MULTI_GAME_COMMBAT; + else + gNet.MultiGameType = MULTI_GAME_AI_BOTS; + +#if 0 //def NET_MODE_MASTER_SLAVE + if (!NetModeOverride) + { + if (numplayers <= 4) + NetBroadcastMode = TRUE; + else + NetBroadcastMode = FALSE; + } +#endif + } + + LoadDemoRun(); + // Save off total heap for later calculations + //TotalMemory = Z_AvailHeap(); + //DSPRINTF(ds,"Available Heap before LoadImages = %d", TotalMemory); + //MONO_PRINT(ds); + // Reserve 1.5 megs for normal program use + // Generally, SW is consuming about a total of 11 megs including + // all the cached in graphics, etc. per level, so even on a 16 meg + // system, reserving 1.5 megs is fine. + // Note that on a 16 meg machine, Ken was leaving us about + // 24k for use outside the cache! This was causing out of mem problems + // when songs, etc., greater than the remaining heap were being loaded. + // Even if you pre-cache songs, etc. to help, reserving some heap is + // a very smart idea since the game uses malloc throughout execution. + //ReserveMem = AllocMem(1L<<20); + //if(ReserveMem == 0) MONO_PRINT("Could not allocate 1.5 meg reserve!"); + + // LoadImages will now proceed to steal all the remaining heap space + //_outtext("\n\n\n\n\n\n\n\n"); + //AnimateCacheCursor(); + buildputs("Loading sound and graphics...\n"); + LoadImages("tiles000.art"); + + // Now free it up for later use + /* + if(ReserveMem) + { + // Recalc TotalMemory for later reference + ActualHeap = Z_AvailHeap() + 1536000L; + FreeMem(ReserveMem); + } + */ + + Connect(); + SortBreakInfo(); + //parallaxyoffs = 40; + parallaxyoffs = 0; + parallaxtype = 1; + pskyoff[0] = 0; + pskybits = PlaxBits; + // Default scale value for parallax skies + parallaxyscale = 8192; + + memset(Track, 0, sizeof(Track)); + + memset(Player, 0, sizeof(Player)); + for (i = 0; i < MAX_SW_PLAYERS; i++) + INITLIST(&Player[i].PanelSpriteList); + + LoadKVXFromScript("swvoxfil.txt"); // Load voxels from script file + LoadPLockFromScript("swplock.txt"); // Get Parental Lock setup info + if (!SW_SHAREWARE) + LoadCustomInfoFromScript("swcustom.txt"); // Load user customisation information + + if (!loaddefinitionsfile(deffile)) buildputs("Definitions file loaded.\n"); + + DemoModeMenuInit = TRUE; + // precache as much stuff as you can + if (UserMapName[0] == '\0') + { + AnimateCacheCursor(); + LoadLevel("$dozer.map"); + AnimateCacheCursor(); + SetupPreCache(); + DoTheCache(); + } + else + { + AnimateCacheCursor(); + LoadLevel(UserMapName); + AnimateCacheCursor(); + SetupPreCache(); + DoTheCache(); + } + + Set_GameMode(); + GraphicsMode = TRUE; + SetupAspectRatio(); + + COVERsetbrightness(gs.Brightness,&palette_data[0][0]); + + InitFX(); // JBF: do it down here so we get a hold of the window handle + InitMusic(); + +} + + +/* +Directory of C:\DEV\SW\MIDI +EXECUT11 MID +HROSHMA6 MID +HOSHIA02 MID +INTRO131 MID +KOTEC2 MID +KOTOKI12 MID +NIPPON34 MID +NOKI41 MID +SANAI MID +SIANRA23 MID +TKYO2007 MID +TYTAIK16 MID +YOKOHA03 MID +*/ + +char LevelSong[16]; +short SongLevelNum; +//#ifndef SW_SHAREWARE +LEVEL_INFO LevelInfo[MAX_LEVELS_REG+2] = +{ + {"title.map", "theme.mid", " ", " ", " " }, + {"$bullet.map", "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00" }, + {"$dozer.map", "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00" }, + {"$shrine.map", "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00" }, + {"$woods.map", "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00" }, + {"$whirl.map", "yokoha03.mid", "Rising Son", "5 : 30", "10 : 00" }, + {"$tank.map", "nippon34.mid", "Killing Fields", "1 : 46", "4 : 00" }, + {"$boat.map", "execut11.mid", "Hara-Kiri Harbor", "1 : 56", "4 : 00" }, + {"$garden.map", "execut11.mid", "Zilla's Villa", "1 : 06", "2 : 00" }, + {"$outpost.map", "sanai.mid", "Monastery", "1 : 23", "3 : 00" }, + {"$hidtemp.map", "kotec2.mid", "Raider of the Lost Wang", "2 : 05", "4 : 10" }, + {"$plax1.map", "kotec2.mid", "Sumo Sky Palace", "6 : 32", "12 : 00" }, + {"$bath.map", "yokoha03.mid", "Bath House", "10 : 00", "10 : 00" }, + {"$airport.map", "nippon34.mid", "Unfriendly Skies", "2 : 59", "6 : 00" }, + {"$refiner.map", "kotoki12.mid", "Crude Oil", "2 : 40", "5 : 00" }, + {"$newmine.map", "hoshia02.mid", "Coolie Mines", "2 : 48", "6 : 00" }, + {"$subbase.map", "hoshia02.mid", "Subpen 7", "2 : 02", "4 : 00" }, + {"$rock.map", "kotoki12.mid", "The Great Escape", "3 : 18", "6 : 00" }, + {"$yamato.map", "sanai.mid", "Floating Fortress", "11 : 38", "20 : 00" }, + {"$seabase.map", "kotec2.mid", "Water Torture", "5 : 07", "10 : 00" }, + {"$volcano.map", "kotec2.mid", "Stone Rain", "9 : 15", "20 : 00" }, + {"$shore.map", "kotec2.mid", "Shanghai Shipwreck", "3 : 58", "8 : 00" }, + {"$auto.map", "kotec2.mid", "Auto Maul", "4 : 07", "8 : 00" }, + {"tank.map", "kotec2.mid", "Heavy Metal (DM only)", "10 : 00", "10 : 00" }, + {"$dmwoods.map", "kotec2.mid", "Ripper Valley (DM only)", "10 : 00", "10 : 00" }, + {"$dmshrin.map", "kotec2.mid", "House of Wang (DM only)", "10 : 00", "10 : 00" }, + {"$rush.map", "kotec2.mid", "Lo Wang Rally (DM only)", "10 : 00", "10 : 00" }, + {"shotgun.map", "kotec2.mid", "Ruins of the Ronin (CTF)", "10 : 00", "10 : 00" }, + {"$dmdrop.map", "kotec2.mid", "Killing Fields (CTF)", "10 : 00", "10 : 00" }, + {NULL, NULL, NULL, NULL, NULL} +}; +/*#else +LEVEL_INFO LevelInfo[MAX_LEVELS+2] = // Shareware + { + {"title.map", "theme.mid", " ", " ", " " }, + {"$bullet.map", "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00" }, + {"$dozer.map", "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00" }, + {"$shrine.map", "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00" }, + {"$woods.map", "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00" }, + {NULL, NULL, NULL, NULL, NULL} + }; +#endif*/ + +char EpisodeNames[2][MAX_EPISODE_NAME_LEN+2] = +{ + "^Enter the Wang", + "^Code of Honor" +}; +char EpisodeSubtitles[2][MAX_EPISODE_SUBTITLE_LEN+1] = +{ + "Four levels (Shareware Version)", + "Eighteen levels (Full Version Only)" +}; +char SkillNames[4][MAX_SKILL_NAME_LEN+2] = +{ + "^Tiny grasshopper", + "^I Have No Fear", + "^Who Wants Wang", + "^No Pain, No Gain" +}; + +VOID InitNewGame(VOID) +{ + int i, ready_bak; + int ver_bak; + + //waitforeverybody(); // since ready flag resets after this point, need to carefully sync + + for (i = 0; i < MAX_SW_PLAYERS; i++) + { + // don't jack with the playerreadyflag + ready_bak = Player[i].playerreadyflag; + ver_bak = Player[i].PlayerVersion; + memset(&Player[i], 0, sizeof(Player[i])); + Player[i].playerreadyflag = ready_bak; + Player[i].PlayerVersion = ver_bak; + INITLIST(&Player[i].PanelSpriteList); + } + + memset(puser, 0, sizeof(puser)); +} + +void FindLevelInfo(char *map_name, short *level) +{ + char *ptr; + char buff[16]; + short i,j; + + for (j = 1; j <= MAX_LEVELS; j++) + { + if (LevelInfo[j].LevelName) + { + if (Bstrcasecmp(map_name, LevelInfo[j].LevelName) == 0) + { + *level = j; + return; + } + } + } + + *level = 0; + return; +} + +int ChopTics; +VOID InitLevelGlobals(VOID) +{ + extern char PlayerGravity; + extern short wait_active_check_offset; + //extern short Zombies; + extern int PlaxCeilGlobZadjust, PlaxFloorGlobZadjust; + extern BOOL left_foot; + extern BOOL serpwasseen; + extern BOOL sumowasseen; + extern BOOL zillawasseen; + extern short BossSpriteNum[3]; + + // A few IMPORTANT GLOBAL RESETS + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 + MapSetup(); + //Zombies = 0; + ChopTics = 0; + dimensionmode = 3; + zoom = 768; + PlayerGravity = 24; + wait_active_check_offset = 0; + PlaxCeilGlobZadjust = PlaxFloorGlobZadjust = Z(500); + pskyoff[0] = 0; + pskybits = PlaxBits; + FinishedLevel = FALSE; + AnimCnt = 0; + left_foot = FALSE; + screenpeek = myconnectindex; + + gNet.TimeLimitClock = gNet.TimeLimit; + + serpwasseen = FALSE; + sumowasseen = FALSE; + zillawasseen = FALSE; + memset(BossSpriteNum,-1,sizeof(BossSpriteNum)); +} + +VOID InitLevelGlobals2(VOID) +{ + extern short Bunny_Count; + // GLOBAL RESETS NOT DONE for LOAD GAME + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + InitTimingVars(); + TotalKillable = 0; + Bunny_Count = 0; +} + +VOID +InitLevel(VOID) +{ + static int DemoNumber = 0; + + MONO_PRINT("InitLevel"); + Terminate3DSounds(); + + // A few IMPORTANT GLOBAL RESETS + InitLevelGlobals(); + MONO_PRINT("InitLevelGlobals"); + if (!DemoMode) + StopSong(); + + if (LoadGameOutsideMoveLoop) + { + MONO_PRINT("Returning from InitLevel"); + return; + } + + InitLevelGlobals2(); + MONO_PRINT("InitLevelGlobals2"); + if (DemoMode) + { + Level = 0; + NewGame = TRUE; + DemoInitOnce = FALSE; + strcpy(DemoFileName, DemoName[DemoNumber]); + DemoNumber++; + if (!DemoName[DemoNumber][0]) + DemoNumber = 0; + + // read header and such + DemoPlaySetup(); + + strcpy(LevelName, DemoLevelName); + + FindLevelInfo(LevelName, &Level); + if (Level > 0) + { + strcpy(LevelSong, LevelInfo[Level].SongName); + strcpy(LevelName, LevelInfo[Level].LevelName); + UserMapName[0] = '\0'; + } + else + { + strcpy(UserMapName, DemoLevelName); + Level = 0; + } + + } + else + { + if (Level < 0) + Level = 0; + + if (Level > MAX_LEVELS) + Level = 1; + + // extra code in case something is resetting these values + if (NewGame) + { + //Level = 1; + //DemoPlaying = FALSE; + DemoMode = FALSE; + //DemoRecording = FALSE; + //DemoEdit = FALSE; + } + + if (UserMapName[0]) + { + strcpy(LevelName, UserMapName); + + Level = 0; + FindLevelInfo(UserMapName, &Level); + + if (Level > 0) + { + // user map is part of game - treat it as such + strcpy(LevelSong, LevelInfo[Level].SongName); + strcpy(LevelName, LevelInfo[Level].LevelName); + UserMapName[0] = '\0'; + } + } + else + { + strcpy(LevelName, LevelInfo[Level].LevelName); + strcpy(LevelSong, LevelInfo[Level].SongName); + } + } + + PlayingLevel = Level; + + if (NewGame) + InitNewGame(); + + LoadingLevelScreen(LevelName); + MONO_PRINT("LoadintLevelScreen"); + if (!DemoMode && !DemoInitOnce) + DemoPlaySetup(); + + LoadLevel(LevelName); + + if (Bstrcasecmp(CacheLastLevel, LevelName) != 0) + // clears gotpic and does some bit setting + SetupPreCache(); + else + memset(gotpic,0,sizeof(gotpic)); + + if (sector[0].extra != -1) + { + NormalVisibility = visibility = sector[0].extra; + sector[0].extra = 0; + } + else + NormalVisibility = visibility; + + // + // Do Player stuff first + // + + InitAllPlayers(); + +#if DEBUG + // fake Multi-player game setup + if (FakeMultiNumPlayers && !BotMode) + { + BYTE i; + + // insert all needed players except the first one - its already tere + for (i = 0; i < FakeMultiNumPlayers - 1; i++) + { + ManualPlayerInsert(Player); + // reset control back to 1st player + myconnectindex = 0; + screenpeek = 0; + } + } +#endif + + // Put in the BOTS if called for + if (FakeMultiNumPlayers && BotMode) + { + BYTE i; + + // insert all needed players except the first one - its already tere + for (i = 0; i < FakeMultiNumPlayers; i++) + { + BotPlayerInsert(Player); + // reset control back to 1st player + myconnectindex = 0; + screenpeek = 0; + } + } + + QueueReset(); + PreMapCombineFloors(); + InitMultiPlayerInfo(); + InitAllPlayerSprites(); + + // + // Do setup for sprite, track, panel, sector, etc + // + + // Set levels up + InitTimingVars(); + + SpriteSetup(); + SpriteSetupPost(); // post processing - already gone once through the loop + InitLighting(); + + TrackSetup(); + + PlayerPanelSetup(); + MapSetup(); + SectorSetup(); + JS_InitMirrors(); + JS_InitLockouts(); // Setup the lockout linked lists + JS_ToggleLockouts(); // Init lockouts on/off + + PlaceSectorObjectsOnTracks(); + PlaceActorsOnTracks(); + PostSetupSectorObject(); + SetupMirrorTiles(); + initlava(); + + SongLevelNum = Level; + + if (DemoMode) + { + DisplayDemoText(); + } + + + if (ArgCheat) + { + BOOL bak = gs.Messages; + gs.Messages = FALSE; + EveryCheatToggle(&Player[0],NULL); + gs.Messages = bak; + GodMode = TRUE; + } + + // reset NewGame + NewGame = FALSE; + + DSPRINTF(ds,"End of InitLevel..."); + MONO_PRINT(ds); + +#if 0 +#if DEBUG + if (!cansee(43594, -92986, 0x3fffffff, 290, + 43180, -91707, 0x3fffffff, 290)) + { + DSPRINTF(ds,"cansee failed"); + MONO_PRINT(ds); + } +#endif +#endif + +} + + +VOID +TerminateLevel(VOID) +{ + VOID pClearSpriteList(PLAYERp pp); + int i, nexti, stat, pnum, ndx; + SECT_USERp *sectu; + +//HEAP_CHECK(); + + DemoTerm(); + + // Free any track points + for (ndx = 0; ndx < MAX_TRACKS; ndx++) + { + if (Track[ndx].TrackPoint) + { + FreeMem(Track[ndx].TrackPoint); + // !JIM! I added null assigner + Track[ndx].TrackPoint = NULL; + } + } + + // Clear the tracks + memset(Track, 0, sizeof(Track)); + + StopSound(); + Terminate3DSounds(); // Kill the 3d sounds linked list + //ClearSoundLocks(); + + // Clear all anims and any memory associated with them + // Clear before killing sprites - save a little time + //AnimClear(); + + for (stat = STAT_PLAYER0; stat < STAT_PLAYER0 + numplayers; stat++) + { + + pnum = stat - STAT_PLAYER0; + + TRAVERSE_SPRITE_STAT(headspritestat[stat], i, nexti) + { + if (User[i]) + memcpy(&puser[pnum], User[i], sizeof(USER)); + } + } + + // Kill User memory and delete sprites + // for (stat = 0; stat < STAT_ALL; stat++) + for (stat = 0; stat < MAXSTATUS; stat++) + { + TRAVERSE_SPRITE_STAT(headspritestat[stat], i, nexti) + { + KillSprite(i); + } + } + + // Free SectUser memory + for (sectu = &SectUser[0]; + sectu < &SectUser[MAXSECTORS]; + sectu++) + { + if (*sectu) + { + ////DSPRINTF(ds,"Sect User Free %d",sectu-SectUser); + //MONO_PRINT(ds); + FreeMem(*sectu); + *sectu = NULL; + } + } + + //memset(&User[0], 0, sizeof(User)); + memset(&SectUser[0], 0, sizeof(SectUser)); + + TRAVERSE_CONNECT(pnum) + { + PLAYERp pp = Player + pnum; + + // Free panel sprites for players + pClearSpriteList(pp); + + pp->DoPlayerAction = NULL; + + pp->SpriteP = NULL; + pp->PlayerSprite = -1; + + pp->UnderSpriteP = NULL; + pp->PlayerUnderSprite = -1; + + memset(pp->HasKey, 0, sizeof(pp->HasKey)); + + //pp->WpnFlags = 0; + pp->CurWpn = NULL; + + memset(pp->Wpn, 0, sizeof(pp->Wpn)); + memset(pp->InventorySprite, 0, sizeof(pp->InventorySprite)); + memset(pp->InventoryTics, 0, sizeof(pp->InventoryTics)); + + pp->Killer = -1; + + INITLIST(&pp->PanelSpriteList); + } + + JS_UnInitLockouts(); + +//HEAP_CHECK(); +} + +VOID +NewLevel(VOID) +{ + + DSPRINTF(ds,"NewLevel"); + MONO_PRINT(ds); + + if (DemoPlaying) + { + FX_SetVolume(0); // Shut the hell up while game is loading! + InitLevel(); + InitRunLevel(); + + DemoInitOnce = FALSE; + if (DemoMode) + { + if (DemoModeMenuInit) + { + DemoModeMenuInit = FALSE; + KEY_PRESSED(KEYSC_ESC) = TRUE; + } + } + + DemoPlayBack(); + + if (DemoRecording && DemoEdit) + { + RunLevel(); + } + } + else + { + DSPRINTF(ds,"Calling FX_SetVolume"); + MONO_PRINT(ds); + FX_SetVolume(0); // Shut the hell up while game is loading! + + DSPRINTF(ds,"Calling InitLevel"); + MONO_PRINT(ds); + InitLevel(); + + DSPRINTF(ds,"Calling RunLevel"); + MONO_PRINT(ds); + RunLevel(); + + if (!QuitFlag) + { + // for good measure do this + ready2send = 0; + waitforeverybody(); + } + + StatScreen(&Player[myconnectindex]); + } + + if (LoadGameFromDemo) + LoadGameFromDemo = FALSE; + else + TerminateLevel(); + + InGame = FALSE; + + if (SW_SHAREWARE) + { + if (FinishAnim) + MenuLevel(); + } + else + { + if (FinishAnim == ANIM_ZILLA || FinishAnim == ANIM_SERP) + MenuLevel(); + } + FinishAnim = 0; +} + +VOID +ResetKeys(VOID) +{ + int i; + + for (i = 0; i < MAXKEYBOARDSCAN; i++) + { + KEY_PRESSED(i) = 0; + } +} + +BOOL +KeyPressed(VOID) +{ + int i; + + for (i = 0; i < MAXKEYBOARDSCAN; i++) + { + if (KEY_PRESSED(i)) + return TRUE; + } + + return FALSE; +} + +BYTEp +KeyPressedRange(BYTEp kb, BYTEp ke) +{ + BYTEp k; + + for (k = kb; k <= ke; k++) + { + if (*k) + return k; + } + + return NULL; +} + +VOID +ResetKeyRange(BYTEp kb, BYTEp ke) +{ + BYTEp k; + + for (k = kb; k <= ke; k++) + { + *k = 0; + } +} + + +VOID +LogoLevel(VOID) +{ + char called; + int fin; + unsigned char backup_pal[256*3]; + unsigned char pal[PAL_SIZE]; + unsigned char tempbuf[256]; + unsigned char *palook_bak = palookup[0]; + UserInput uinfo = { FALSE, FALSE, dir_None }; + int i; + + + DSPRINTF(ds,"LogoLevel..."); + MONO_PRINT(ds); + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + palookup[0] = tempbuf; + + DSPRINTF(ds,"Created palookup..."); + MONO_PRINT(ds); + + // start music at logo + strcpy(LevelSong,"theme.mid"); + PlaySong(LevelSong, RedBookSong[0], TRUE, TRUE); + + DSPRINTF(ds,"After music stuff..."); + MONO_PRINT(ds); + + //GetPaletteFromVESA(pal); + //memcpy(backup_pal, pal, PAL_SIZE); + + DSPRINTF(ds,"Got Palette from VESA..."); + MONO_PRINT(ds); + + // PreCache Anim + LoadAnm(0); + + if ((fin = kopen4load("3drealms.pal", 0)) != -1) + { + kread(fin, pal, PAL_SIZE); + kclose(fin); + setbrightness(gs.Brightness, pal, 2); + } + DSPRINTF(ds,"Just read in 3drealms.pal..."); + MONO_PRINT(ds); + + //FadeOut(0, 0); + ready2send = 0; + totalclock = 0; + ototalclock = 0; + + DSPRINTF(ds,"About to display 3drealms pic..."); + MONO_PRINT(ds); + + clearview(0); + rotatesprite(0, 0, RS_SCALE, 0, THREED_REALMS_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + nextpage(); + //FadeIn(0, 3); + + ResetKeys(); + while (TRUE) + { + handleevents(); + CONTROL_GetUserInput(&uinfo); + CONTROL_ClearUserInput(&uinfo); + if (quitevent) { QuitFlag = TRUE; break; } + + // taken from top of faketimerhandler + // limits checks to max of 40 times a second + if (totalclock >= ototalclock + synctics) + { + ototalclock += synctics; + } + + if (totalclock > 5*120 || KeyPressed() || uinfo.button0 || uinfo.button1) + { + break; + } + } + + palookup[0] = palook_bak; + + clearview(0); + nextpage(); + //SetPaletteToVESA(backup_pal); + setbrightness(gs.Brightness, &palette_data[0][0], 2); + + // put up a blank screen while loading + + DSPRINTF(ds,"End of LogoLevel..."); + MONO_PRINT(ds); + +} + +VOID +CreditsLevel(VOID) +{ + char called; + int fin; + int i; + int curpic; + int handle; + ULONG timer = 0; + int zero=0; + short save; +#define CREDITS1_PIC 5111 +#define CREDITS2_PIC 5118 + + // put up a blank screen while loading + + // get rid of all PERM sprites! + flushperms(); + save = gs.BorderNum; + SetBorder(Player + myconnectindex,0); + ClearStartMost(); + gs.BorderNum = save; + clearview(0); + nextpage(); + + // Lo Wang feel like singing! + handle = PlaySound(DIGI_JG95012,&zero,&zero,&zero,v3df_none); + + if (handle > 0) + while (FX_SoundActive(handle)) ; + + // try 14 then 2 then quit + if (!PlaySong(NULL, 14, FALSE, TRUE)) + { + if (!PlaySong(NULL, 2, FALSE, TRUE)) + { + handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none); + if (handle > 0) + while (FX_SoundActive(handle)) handleevents(); + return; + } + } + + ready2send = 0; + totalclock = 0; + ototalclock = 0; + + ResetKeys(); + curpic = CREDITS1_PIC; + + while (TRUE) + { + // taken from top of faketimerhandler + // limits checks to max of 40 times a second + if (totalclock >= ototalclock + synctics) + { + ototalclock += synctics; + timer += synctics; + } + + rotatesprite(0, 0, RS_SCALE, 0, curpic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + + nextpage(); + + if (timer > 8*120) + { + curpic = CREDITS2_PIC; + } + + if (timer > 16*120) + { + timer = 0; + curpic = CREDITS1_PIC; + } + + + if (!SongIsPlaying()) + break; + + if (KEY_PRESSED(KEYSC_ESC)) + break; + } + + // put up a blank screen while loading + clearview(0); + nextpage(); + ResetKeys(); + StopSong(); +} + + +VOID +SybexScreen(VOID) +{ + if (!SW_SHAREWARE) return; + + if (CommEnabled) + return; + + rotatesprite(0, 0, RS_SCALE, 0, 5261, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + nextpage(); + + ResetKeys(); + while (!KeyPressed() && !quitevent) handleevents(); +} + +// CTW REMOVED +/* +VOID +TenScreen(VOID) + { + char called; + int fin; + char backup_pal[256*3]; + char pal[PAL_SIZE]; + char tempbuf[256]; + char *palook_bak = palookup[0]; + int i; + ULONG bak; + int bakready2send; + + if (CommEnabled) + return; + + bak = totalclock; + + flushperms(); + clearview(0); + nextpage(); + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + palookup[0] = tempbuf; + + GetPaletteFromVESA(pal); + memcpy(backup_pal, pal, PAL_SIZE); + + if ((fin = kopen4load("ten.pal", 0)) != -1) + { + kread(fin, pal, PAL_SIZE); + kclose(fin); + } + + // palette to black + FadeOut(0, 0); + bakready2send = ready2send; + //totalclock = 0; + //ototalclock = 0; + + flushperms(); + // draw it + rotatesprite(0, 0, RS_SCALE, 0, TEN_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + // bring to the front - still back palette + nextpage(); + // set pal + SetPaletteToVESA(pal); + //FadeIn(0, 3); + ResetKeys(); + + while (!KeyPressed()); + + palookup[0] = palook_bak; + + clearview(0); + nextpage(); + SetPaletteToVESA(backup_pal); + + // put up a blank screen while loading + clearview(0); + nextpage(); + + ready2send = bakready2send; + totalclock = bak; + } +*/ +// CTW REMOVED END + +VOID +TitleLevel(VOID) +{ + char called; + int fin; + unsigned char backup_pal[256*3]; + unsigned char pal[PAL_SIZE]; + unsigned char tempbuf[256]; + unsigned char *palook_bak = palookup[0]; + int i; + + for (i = 0; i < 256; i++) + tempbuf[i] = i; + palookup[0] = tempbuf; + + //GetPaletteFromVESA(pal); + //memcpy(backup_pal, pal, PAL_SIZE); + + clearview(0); + nextpage(); + +// if ((fin = kopen4load("title.pal", 0)) != -1) +// { +// kread(fin, pal, PAL_SIZE); +// kclose(fin); +// SetPaletteToVESA(pal); +// } + +// clearview(0); +// nextpage(); + + //FadeOut(0, 0); + ready2send = 0; + totalclock = 0; + ototalclock = 0; + + rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + nextpage(); + //FadeIn(0, 3); + + ResetKeys(); + while (TRUE) + { + handleevents(); + OSD_DispatchQueued(); + + // taken from top of faketimerhandler + // limits checks to max of 40 times a second + if (totalclock >= ototalclock + synctics) + { + //void MNU_CheckForMenusAnyKey( void ); + + ototalclock += synctics; + //MNU_CheckForMenusAnyKey(); + } + + //if (UsingMenus) + // MNU_DrawMenu(); + + //drawscreen as fast as you can + rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + + nextpage(); + + if (totalclock > 5*120 || KeyPressed()) + { + DemoMode = TRUE; + DemoPlaying = TRUE; + break; + } + } + + palookup[0] = palook_bak; + +// clearview(0); +// nextpage(); + //SetPaletteToVESA(backup_pal); + + // put up a blank screen while loading +// clearview(0); +// nextpage(); +} + + +VOID DrawMenuLevelScreen(VOID) +{ + flushperms(); + clearview(0); + rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 20, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); +} + +VOID DrawStatScreen(VOID) +{ + flushperms(); + clearview(0); + rotatesprite(0, 0, RS_SCALE, 0, STAT_SCREEN_PIC, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); +} + +VOID DrawLoadLevelScreen(VOID) +{ + flushperms(); + clearview(0); + rotatesprite(0, 0, RS_SCALE, 0, TITLE_PIC, 20, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); +} + +short PlayerQuitMenuLevel = -1; + +VOID +IntroAnimLevel(VOID) +{ + DSPRINTF(ds,"IntroAnimLevel"); + MONO_PRINT(ds); + playanm(0); +} + +VOID +MenuLevel(VOID) +{ + BOOL MNU_StartNetGame(void); + char called; + int fin; + extern int totalclocklock; + short w,h; + + DSPRINTF(ds,"MenuLevel..."); + MONO_PRINT(ds); + + if (gs.MusicOn) + { + PlaySong(NULL, RedBookSong[0], TRUE, FALSE); + } + + if (AutoNet) + { + DrawMenuLevelScreen(); + + if (CommEnabled) + { + sprintf(ds,"Lo Wang is waiting for other players..."); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 170, ds, 1, 16); + + sprintf(ds,"They are afraid!"); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 180, ds, 1, 16); + } + + nextpage(); + + waitforeverybody(); + FirstTimeIntoGame = TRUE; + MNU_StartNetGame(); + FirstTimeIntoGame = FALSE; + waitforeverybody(); + ExitLevel = FALSE; + FinishedLevel = FALSE; + BorderAdjust = TRUE; + UsingMenus = FALSE; + InMenuLevel = FALSE; + return; + } + + // do demos only if not playing multi play + if (!CommEnabled && numplayers <= 1 && !FinishAnim && !NoDemoStartup) + { + // demos exist - do demo instead + if (DemoName[0][0] != '\0') + { + DemoMode = TRUE; + DemoPlaying = TRUE; + return; + } + } + + DemoMode = FALSE; + DemoPlaying = FALSE; + + clearview(0); + nextpage(); + + //FadeOut(0, 0); + ready2send = 0; + totalclock = 0; + ototalclock = 0; + ExitLevel = FALSE; + InMenuLevel = TRUE; + + DrawMenuLevelScreen(); + + if (CommEnabled) + { + sprintf(ds,"Lo Wang is waiting for other players..."); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 170, ds, 1, 16); + + sprintf(ds,"They are afraid!"); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 180, ds, 1, 16); + } + + nextpage(); + //FadeIn(0, 3); + + waitforeverybody(); + + // don't allow BorderAdjusting in these menus + BorderAdjust = FALSE; + + ResetKeys(); + + if (SW_SHAREWARE) + { + // go to ordering menu only if shareware + if (FinishAnim) + { + KEY_PRESSED(KEYSC_ESC) = 1; + ControlPanelType = ct_ordermenu; + FinishAnim = 0; + } + } + else + { + FinishAnim = 0; + } + + while (TRUE) + { + handleevents(); + OSD_DispatchQueued(); + + if (quitevent) QuitFlag = TRUE; + + // taken from top of faketimerhandler + // limits checks to max of 40 times a second + if (totalclock >= ototalclock + synctics) + { + ototalclock += synctics; + MNU_CheckForMenusAnyKey(); + if (CommEnabled) + getpackets(); + } + + if (CommEnabled) + { + if (MultiPlayQuitFlag) + { + short pnum; + BYTE pbuf[1]; + QuitFlag = TRUE; + pbuf[0] = PACKET_TYPE_MENU_LEVEL_QUIT; + netbroadcastpacket(pbuf, 1); // TENSW + break; + } + + if (PlayerQuitMenuLevel >= 0) + { + MenuCommPlayerQuit(PlayerQuitMenuLevel); + PlayerQuitMenuLevel = -1; + } + } + + if (ExitLevel) + { + // Quiting Level + ExitLevel = FALSE; + break; + } + + if (QuitFlag) + { + // Quiting Game + break; + } + + // force the use of menus at all time + if (!UsingMenus && !ConPanel) + { + KEY_PRESSED(KEYSC_ESC) = TRUE; + MNU_CheckForMenusAnyKey(); + } + + // must lock the clock for drawing so animations will happen + totalclocklock = totalclock; + + //drawscreen as fast as you can + DrawMenuLevelScreen(); + + if (UsingMenus) + MNU_DrawMenu(); + + nextpage(); + } + + BorderAdjust = TRUE; + //LoadGameOutsideMoveLoop = FALSE; + KEY_PRESSED(KEYSC_ESC) = FALSE; + KB_ClearKeysDown(); + //ExitMenus(); + UsingMenus = FALSE; + InMenuLevel = FALSE; + clearview(0); + nextpage(); +} + +VOID +SceneLevel(VOID) +{ + BOOL dp_bak; + BOOL dm_bak; + FILE *fin; +#define CINEMATIC_DEMO_FILE "$scene.dmo" + + // make sure it exists + if ((fin = fopen(CINEMATIC_DEMO_FILE,"rb")) == NULL) + return; + else + fclose(fin); + + strcpy(DemoFileName,CINEMATIC_DEMO_FILE); + + dp_bak = DemoPlaying; + dm_bak = DemoMode; + + DemoMode = TRUE; + DemoPlaying = TRUE; + DemoOverride = TRUE; + InitLevel(); + DemoOverride = FALSE; + + ScenePlayBack(); + TerminateLevel(); + DemoMode = dm_bak; + DemoPlaying = dp_bak; +} + +VOID +LoadingLevelScreen(char *level_name) +{ + short w,h; + extern BOOL DemoMode; + extern char *MNU_LevelName[28]; + DrawLoadLevelScreen(); + + if (DemoMode) + sprintf(ds,"DEMO"); + else + sprintf(ds,"ENTERING"); + + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 170, ds,1,16); + + if (UserMapName[0]) + sprintf(ds,"%s",UserMapName); + else + sprintf(ds,"%s",LevelInfo[Level].Description); + + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 180, ds,1,16); + + nextpage(); +} + +VOID +gNextState(STATEp *State) +{ + // Transition to the next state + *State = (*State)->NextState; + + if (TEST((*State)->Tics, SF_QUICK_CALL)) + { + (*(*State)->Animator)(0); + *State = (*State)->NextState; + } +} + +// Generic state control +VOID +gStateControl(STATEp *State, int *tics) +{ + *tics += synctics; + + // Skip states if too much time has passed + while (*tics >= (*State)->Tics) + { + // Set Tics + *tics -= (*State)->Tics; + gNextState(State); + } + + // Call the correct animator + if ((*State)->Animator) + (*(*State)->Animator)(0); +} + +int BonusPunchSound(short SpriteNum) +{ + PLAYERp pp = Player + myconnectindex; + PlaySound(DIGI_PLAYERYELL3, &pp->posx, &pp->posy, &pp->posz, v3df_none); + return 0; +} + +int BonusKickSound(short SpriteNum) +{ + PLAYERp pp = Player + myconnectindex; + PlaySound(DIGI_PLAYERYELL2, &pp->posx, &pp->posy, &pp->posz, v3df_none); + return 0; +} + +int BonusGrabSound(short SpriteNum) +{ + PLAYERp pp = Player + myconnectindex; + PlaySound(DIGI_BONUS_GRAB, &pp->posx, &pp->posy, &pp->posz, v3df_none); + return 0; +} + +VOID +BonusScreen(PLAYERp pp) +{ + int minutes,seconds,second_tics; + extern BOOL FinishedLevel; + extern int PlayClock; + extern short LevelSecrets; + extern short TotalKillable; + short w,h; + short pic,limit; + int zero=0; + int handle = 0; + short LI_Num; + + +#define BONUS_SCREEN_PIC 5120 +#define BONUS_ANIM 5121 +#define BONUS_ANIM_FRAMES (5159-5121) + +#define BREAK_LIGHT_RATE 18 + +#define BONUS_PUNCH 5121 +#define BONUS_KICK 5136 +#define BONUS_GRAB 5151 +#define BONUS_REST 5121 + +#define BONUS_TICS 8 +#define BONUS_GRAB_TICS 20 +#define BONUS_REST_TICS 50 + + static STATE s_BonusPunch[] = + { + {BONUS_PUNCH + 0, BONUS_TICS, NULL, &s_BonusPunch[1]}, + {BONUS_PUNCH + 1, BONUS_TICS, NULL, &s_BonusPunch[2]}, + {BONUS_PUNCH + 2, BONUS_TICS, NULL, &s_BonusPunch[3]}, + {BONUS_PUNCH + 2, 0|SF_QUICK_CALL, BonusPunchSound, &s_BonusPunch[4]}, + {BONUS_PUNCH + 3, BONUS_TICS, NULL, &s_BonusPunch[5]}, + {BONUS_PUNCH + 4, BONUS_TICS, NULL, &s_BonusPunch[6]}, + {BONUS_PUNCH + 5, BONUS_TICS, NULL, &s_BonusPunch[7]}, + {BONUS_PUNCH + 6, BONUS_TICS, NULL, &s_BonusPunch[8]}, + {BONUS_PUNCH + 7, BONUS_TICS, NULL, &s_BonusPunch[9]}, + {BONUS_PUNCH + 8, BONUS_TICS, NULL, &s_BonusPunch[10]}, + {BONUS_PUNCH + 9, BONUS_TICS, NULL, &s_BonusPunch[11]}, + {BONUS_PUNCH + 10, BONUS_TICS, NULL, &s_BonusPunch[12]}, + {BONUS_PUNCH + 11, BONUS_TICS, NULL, &s_BonusPunch[13]}, + {BONUS_PUNCH + 12, BONUS_TICS, NULL, &s_BonusPunch[14]}, + {BONUS_PUNCH + 14, 90, NULL, &s_BonusPunch[15]}, + {BONUS_PUNCH + 14, BONUS_TICS, NULL, &s_BonusPunch[15]}, + }; + + static STATE s_BonusKick[] = + { + {BONUS_KICK + 0, BONUS_TICS, NULL, &s_BonusKick[1]}, + {BONUS_KICK + 1, BONUS_TICS, NULL, &s_BonusKick[2]}, + {BONUS_KICK + 2, BONUS_TICS, NULL, &s_BonusKick[3]}, + {BONUS_KICK + 2, 0|SF_QUICK_CALL, BonusKickSound, &s_BonusKick[4]}, + {BONUS_KICK + 3, BONUS_TICS, NULL, &s_BonusKick[5]}, + {BONUS_KICK + 4, BONUS_TICS, NULL, &s_BonusKick[6]}, + {BONUS_KICK + 5, BONUS_TICS, NULL, &s_BonusKick[7]}, + {BONUS_KICK + 6, BONUS_TICS, NULL, &s_BonusKick[8]}, + {BONUS_KICK + 7, BONUS_TICS, NULL, &s_BonusKick[9]}, + {BONUS_KICK + 8, BONUS_TICS, NULL, &s_BonusKick[10]}, + {BONUS_KICK + 9, BONUS_TICS, NULL, &s_BonusKick[11]}, + {BONUS_KICK + 10, BONUS_TICS, NULL, &s_BonusKick[12]}, + {BONUS_KICK + 11, BONUS_TICS, NULL, &s_BonusKick[13]}, + {BONUS_KICK + 12, BONUS_TICS, NULL, &s_BonusKick[14]}, + {BONUS_KICK + 14, 90, NULL, &s_BonusKick[15]}, + {BONUS_KICK + 14, BONUS_TICS, NULL, &s_BonusKick[15]}, + }; + + static STATE s_BonusGrab[] = + { + {BONUS_GRAB + 0, BONUS_GRAB_TICS, NULL, &s_BonusGrab[1]}, + {BONUS_GRAB + 1, BONUS_GRAB_TICS, NULL, &s_BonusGrab[2]}, + {BONUS_GRAB + 2, BONUS_GRAB_TICS, NULL, &s_BonusGrab[3]}, + {BONUS_GRAB + 2, 0|SF_QUICK_CALL, BonusGrabSound, &s_BonusGrab[4]}, + {BONUS_GRAB + 3, BONUS_GRAB_TICS, NULL, &s_BonusGrab[5]}, + {BONUS_GRAB + 4, BONUS_GRAB_TICS, NULL, &s_BonusGrab[6]}, + {BONUS_GRAB + 5, BONUS_GRAB_TICS, NULL, &s_BonusGrab[7]}, + {BONUS_GRAB + 6, BONUS_GRAB_TICS, NULL, &s_BonusGrab[8]}, + {BONUS_GRAB + 7, BONUS_GRAB_TICS, NULL, &s_BonusGrab[9]}, + {BONUS_GRAB + 8, BONUS_GRAB_TICS, NULL, &s_BonusGrab[10]}, + {BONUS_GRAB + 9, 90, NULL, &s_BonusGrab[11]}, + {BONUS_GRAB + 9, BONUS_GRAB_TICS, NULL, &s_BonusGrab[11]}, + }; + +#if 1 // Turned off the standing animate because he looks like a FAG! + static STATE s_BonusRest[] = + { + {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[1]}, + {BONUS_REST + 1, BONUS_REST_TICS, NULL, &s_BonusRest[2]}, + {BONUS_REST + 2, BONUS_REST_TICS, NULL, &s_BonusRest[3]}, + {BONUS_REST + 1, BONUS_REST_TICS, NULL, &s_BonusRest[0]}, + }; +#else + static STATE s_BonusRest[] = + { + {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[1]}, + {BONUS_REST + 0, BONUS_REST_TICS, NULL, &s_BonusRest[0]}, + }; +#endif + + static STATEp s_BonusAnim[] = + { + s_BonusPunch, + s_BonusKick, + s_BonusGrab + }; + + STATEp State = s_BonusRest; + + int Tics = 0; + int line = 0; + BOOL BonusDone; + UserInput uinfo = { FALSE, FALSE, dir_None }; + + if (Level < 0) Level = 0; + + clearview(0); + nextpage(); + + KB_ClearKeysDown(); + + totalclock = ototalclock = 0; + limit = synctics; + + if (gs.MusicOn) + { + PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE); + } + + // special case code because I don't care any more! + if (FinishAnim) + { + flushperms(); + rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + nextpage(); + FadeIn(0,0); + } + + BonusDone = FALSE; + while (!BonusDone) + { + handleevents(); + + // taken from top of faketimerhandler + if (totalclock < ototalclock + limit) + { + continue; + } + ototalclock += limit; + + CONTROL_GetUserInput(&uinfo); + CONTROL_ClearUserInput(&uinfo); + if (KEY_PRESSED(KEYSC_SPACE) || KEY_PRESSED(KEYSC_ENTER) || uinfo.button0 || uinfo.button1) + { + if (State >= s_BonusRest && State < &s_BonusRest[SIZ(s_BonusRest)]) + { + State = s_BonusAnim[STD_RANDOM_RANGE(SIZ(s_BonusAnim))]; + Tics = 0; + } + } + + gStateControl(&State, &Tics); + rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + + if (UserMapName[0]) + { + sprintf(ds,"%s",UserMapName); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19); + } + else + { + if (PlayingLevel <= 1) + PlayingLevel = 1; + sprintf(ds,"%s",LevelInfo[PlayingLevel].Description); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19); + } + + sprintf(ds,"Completed"); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 30, ds,1,19); + + rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); + +#define BONUS_LINE(i) (50 + ((i)*20)) + + line = 0; + second_tics = (PlayClock/120); + minutes = (second_tics/60); + seconds = (second_tics%60); + sprintf(ds,"Your Time: %2d : %02d", minutes, seconds); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(60, BONUS_LINE(line), ds,1,16); + + if (!UserMapName[0]) + { + line++; + sprintf(ds,"3D Realms Best Time: %s", LevelInfo[PlayingLevel].BestTime); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(40, BONUS_LINE(line), ds,1,16); + + line++; + sprintf(ds,"Par Time: %s", LevelInfo[PlayingLevel].ParTime); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(40, BONUS_LINE(line), ds,1,16); + } + + + // always read secrets and kills from the first player + line++; + sprintf(ds,"Secrets: %d / %d", Player->SecretsFound, LevelSecrets); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(60, BONUS_LINE(line), ds,1,16); + + line++; + sprintf(ds,"Kills: %d / %d", Player->Kills, TotalKillable); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(60, BONUS_LINE(line), ds,1,16); + + + sprintf(ds,"Press SPACE to continue"); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 185, ds,1,19); + + nextpage(); + ScreenCaptureKeys(); + + if (State == State->NextState) + BonusDone = TRUE; + } + + StopSound(); + Terminate3DSounds(); +} + +VOID EndGameSequence(VOID) +{ + BOOL anim_ok = TRUE; + FadeOut(0, 5); + + if ((gs.ParentalLock || Global_PLock) && FinishAnim == ANIM_SUMO) + anim_ok = FALSE; + + if (anim_ok) + playanm(FinishAnim); + + BonusScreen(Player + myconnectindex); + + ExitLevel = FALSE; + QuitFlag = FALSE; + AutoNet = FALSE; + + if (FinishAnim == ANIM_ZILLA) + CreditsLevel(); + + ExitLevel = FALSE; + QuitFlag = FALSE; + AutoNet = FALSE; + + if (SW_SHAREWARE) + { + Level = 0; + } + else + { + if (Level == 4 || Level == 20) + { + //CDAudio_Stop(); + //CDAudio_Play(2,TRUE); // Play theme after game ends + Level=0; + } + else + Level++; + } +} + +VOID +StatScreen(PLAYERp mpp) +{ + int minutes,seconds,second_tics; + extern BOOL FinishedLevel; + extern int PlayClock; + extern short LevelSecrets; + extern short TotalKillable; + short w,h; + int zero=0; + int handle=0; + + short rows,cols,i,j; + PLAYERp pp = NULL; + int x,y; + short death_total[MAX_SW_PLAYERS_REG]; + short kills[MAX_SW_PLAYERS_REG]; + short pal; + +#define STAT_START_X 20 +#define STAT_START_Y 85 +#define STAT_OFF_Y 9 +#define STAT_HEADER_Y 14 + +#define SM_SIZ(num) ((num)*4) + +#define STAT_TABLE_X (STAT_START_X + SM_SIZ(15)) +#define STAT_TABLE_XOFF SM_SIZ(6) + + // No stats in bot games + //if (BotMode) return; + + ResetPalette(mpp); + COVER_SetReverb(0); // Reset reverb + StopSound(); + + if (FinishAnim) + { + EndGameSequence(); + return; + } + + if (gNet.MultiGameType != MULTI_GAME_COMMBAT) + { + if (!FinishedLevel) + return; + BonusScreen(mpp); + return; + } + + flushperms(); + DrawStatScreen(); + + memset(death_total,0,sizeof(death_total)); + memset(kills,0,sizeof(kills)); + + sprintf(ds,"MULTIPLAYER TOTALS"); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 68, ds, 0, 0); + + sprintf(ds,"PRESS SPACE BAR TO CONTINUE"); + MNU_MeasureString(ds, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 189, ds, 0, 0); + + x = STAT_START_X; + y = STAT_START_Y; + + sprintf(ds," NAME 1 2 3 4 5 6 7 8 KILLS"); + DisplayMiniBarSmString(mpp, x, y, 0, ds); + rows = OrigCommPlayers; + cols = OrigCommPlayers; + mpp = Player + myconnectindex; + + y += STAT_HEADER_Y; + + for (i = 0; i < rows; i++) + { + x = STAT_START_X; + pp = Player + i; + + sprintf(ds,"%d", i+1); + DisplayMiniBarSmString(mpp, x, y, 0, ds); + + sprintf(ds," %-13s", pp->PlayerName); + DisplayMiniBarSmString(mpp, x, y, User[pp->PlayerSprite]->spal, ds); + + x = STAT_TABLE_X; + for (j = 0; j < cols; j++) + { + pal = 0; + death_total[j] += pp->KilledPlayer[j]; + + if (i == j) + { + // don't add kill for self or team player + pal = PALETTE_PLAYER0 + 4; + kills[i] -= pp->KilledPlayer[j]; // subtract self kills + } + else if (gNet.TeamPlay) + { + if (User[pp->PlayerSprite]->spal == User[Player[j].PlayerSprite]->spal) + { + // don't add kill for self or team player + pal = PALETTE_PLAYER0 + 4; + kills[i] -= pp->KilledPlayer[j]; // subtract self kills + } + else + kills[i] += pp->KilledPlayer[j]; // kills added here + } + else + { + kills[i] += pp->KilledPlayer[j]; // kills added here + } + + sprintf(ds,"%d", pp->KilledPlayer[j]); + DisplayMiniBarSmString(mpp, x, y, pal, ds); + x += STAT_TABLE_XOFF; + } + + y += STAT_OFF_Y; + } + + + // Deaths + + x = STAT_START_X; + y += STAT_OFF_Y; + + sprintf(ds," DEATHS"); + DisplayMiniBarSmString(mpp, x, y, 0, ds); + x = STAT_TABLE_X; + + for (j = 0; j < cols; j++) + { + sprintf(ds,"%d",death_total[j]); + DisplayMiniBarSmString(mpp, x, y, 0, ds); + x += STAT_TABLE_XOFF; + } + + x = STAT_START_X; + y += STAT_OFF_Y; + + // Kills + x = STAT_TABLE_X + SM_SIZ(50); + y = STAT_START_Y + STAT_HEADER_Y; + + for (i = 0; i < rows; i++) + { + pp = Player + i; + + sprintf(ds,"%d", kills[i]); //pp->Kills); + DisplayMiniBarSmString(mpp, x, y, 0, ds); + + y += STAT_OFF_Y; + } + + nextpage(); + + if (KeyPressed()) + { + while (KeyPressed()) ; + } + + KEY_PRESSED(KEYSC_SPACE) = 0; + KEY_PRESSED(KEYSC_ENTER) = 0; + + if (gs.MusicOn) + { + PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE); + } + + while (!KEY_PRESSED(KEYSC_SPACE) && !KEY_PRESSED(KEYSC_ENTER)) + { + handleevents(); + + ScreenCaptureKeys(); + } + + StopSound(); + Terminate3DSounds(); +} + +VOID +GameIntro(VOID) +{ + + DSPRINTF(ds,"GameIntro..."); + MONO_PRINT(ds); + + if (DemoPlaying) + return; + + // this could probably be taken out and you could select skill level + // from menu to start the game + if (!CommEnabled && UserMapName[0]) + return; + + Level = 1; + + + + + if (!AutoNet) + { + LogoLevel(); + //CreditsLevel(); + //SceneLevel(); + //TitleLevel(); + IntroAnimLevel(); + IntroAnimCount = 0; + } + + MenuLevel(); +} + +VOID +Control(VOID) +{ + + InitGame(); + + MONO_PRINT("InitGame done"); + MNU_InitMenus(); + InGame = TRUE; + GameIntro(); + //NewGame = TRUE; + + while (!QuitFlag) + { + handleevents(); + OSD_DispatchQueued(); + + if (quitevent) QuitFlag = TRUE; + + NewLevel(); + } + + CleanExit = TRUE; + TerminateGame(); +} + + +void +_Assert(char *expr, char *strFile, unsigned uLine) +{ + sprintf(ds, "Assertion failed: %s %s, line %u", expr, strFile, uLine); + MONO_PRINT(ds); + TerminateGame(); +#if 1 //def RENDERTYPEWIN + wm_msgbox(apptitle, ds); +#else + printf("Assertion failed: %s\n %s, line %u\n", expr, strFile, uLine); +#endif + exit(0); +} + + +void +_ErrMsg(char *strFile, unsigned uLine, char *format, ...) +{ + va_list arglist; + + //DSPRINTF(ds, "Error: %s, line %u", strFile, uLine); + //MONO_PRINT(ds); + TerminateGame(); + +#if 1 //def RENDERTYPEWIN + { + char msg[256], *p; + Bsnprintf(msg, sizeof(msg), "Error: %s, line %u\n", strFile, uLine); + p = &msg[strlen(msg)]; + va_start(arglist, format); + Bvsnprintf(msg, sizeof(msg) - (p-msg), format, arglist); + va_end(arglist); + wm_msgbox(apptitle, msg); + } +#else + printf("Error: %s, line %u\n", strFile, uLine); + + va_start(arglist, format); + vprintf(format, arglist); + va_end(arglist); +#endif + + exit(0); +} + +void +dsprintf(char *str, char *format, ...) +{ + va_list arglist; + + va_start(arglist, format); + vsprintf(str, format, arglist); + va_end(arglist); +} + +void +dsprintf_null(char *str, char *format, ...) +{ + va_list arglist; +} + +void MoveLoop(void) +{ + int pnum; + + getpackets(); + + if (PredictionOn && CommEnabled) + { + while (predictmovefifoplc < Player[myconnectindex].movefifoend) + { + DoPrediction(ppp); + } + } + + //While you have new input packets to process... + if (!CommEnabled) + bufferjitter = 0; + + while (Player[myconnectindex].movefifoend - movefifoplc > bufferjitter) + { + //Make sure you have at least 1 packet from everyone else + for (pnum=connecthead; pnum>=0; pnum=connectpoint2[pnum]) + { + if (movefifoplc == Player[pnum].movefifoend) + { + break; + } + } + + //Pnum is >= 0 only if last loop was broken, meaning a player wasn't caught up + if (pnum >= 0) + break; + + domovethings(); + +#if DEBUG + //if (DemoSyncRecord) + // demosync_record(); +#endif + } + + if (!InputMode && !PauseKeySet) + MNU_CheckForMenus(); +} + + +void InitPlayerGameSettings(void) +{ + int pnum; + + // don't jack with auto aim settings if DemoMode is going + // what the hell did I do this for????????? + //if (DemoMode) + // return; + + if (CommEnabled) + { + // everyone gets the same Auto Aim + TRAVERSE_CONNECT(pnum) + { + if (gNet.AutoAim) + SET(Player[pnum].Flags, PF_AUTO_AIM); + else + RESET(Player[pnum].Flags, PF_AUTO_AIM); + } + } + else + { + if (gs.AutoAim) + SET(Player[myconnectindex].Flags, PF_AUTO_AIM); + else + RESET(Player[myconnectindex].Flags, PF_AUTO_AIM); + } + + // everyone had their own Auto Run + if (gs.AutoRun) + SET(Player[myconnectindex].Flags, PF_LOCK_RUN); + else + RESET(Player[myconnectindex].Flags, PF_LOCK_RUN); + + if (gs.MouseAimingOn) + SET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON); + else + RESET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON); +} + + +VOID InitRunLevel(VOID) +{ + int i; + if (DemoEdit) + return; + + if (LoadGameOutsideMoveLoop) + { + int SavePlayClock; + extern int PlayClock; + LoadGameOutsideMoveLoop = FALSE; + // contains what is needed from calls below + if (gs.Ambient) + StartAmbientSound(); + SetCrosshair(); + PlaySong(LevelSong, -1, TRUE, TRUE); + SetRedrawScreen(Player + myconnectindex); + // crappy little hack to prevent play clock from being overwritten + // for load games + SavePlayClock = PlayClock; + InitTimingVars(); + PlayClock = SavePlayClock; + MONO_PRINT("Done with InitRunLevel"); + return; + } + +#if 0 + // ensure we are through the initialization code before sending the game + // version. Otherwise, it is possible to send this too early and have it + // blown away on the other side. + waitforeverybody(); +#endif + + SendVersion(GameVersion); + + waitforeverybody(); + + StopSong(); + + if (Bstrcasecmp(CacheLastLevel, LevelName) != 0) + DoTheCache(); + + if (CachePrintMode) + cachedebug = TRUE; + + // auto aim / auto run / etc + InitPlayerGameSettings(); + + // send packets with player info + InitNetPlayerOptions(); + + // Initialize Game part of network code (When ready2send != 0) + InitNetVars(); + + { + int track; + if (Level == 0) + { + track = RedBookSong[4+RANDOM_RANGE(10)]; + } + else + { + track = RedBookSong[Level]; + } + PlaySong(LevelSong, track, TRUE, TRUE); + } + + InitPrediction(&Player[myconnectindex]); + + if (!DemoInitOnce) + DemoRecordSetup(); + + // everything has been inited at least once for RECORD + DemoInitOnce = TRUE; + +//DebugWriteLoc(__FILE__, __LINE__); + waitforeverybody(); + + CheckVersion(GameVersion); + + // IMPORTANT - MUST be right before game loop AFTER waitforeverybody + InitTimingVars(); + + SetRedrawScreen(Player + myconnectindex); + + FX_SetVolume(gs.SoundVolume); // Turn volume back up + if (gs.Ambient) + StartAmbientSound(); +} + +VOID +RunLevel(VOID) +{ + int i; + InitRunLevel(); + + FX_SetVolume(gs.SoundVolume); + SetSongVolume(gs.MusicVolume); + +#if 0 + waitforeverybody(); +#endif + ready2send = 1; + + while (TRUE) + { + handleevents(); + OSD_DispatchQueued(); + + if (quitevent) QuitFlag = TRUE; + + //MONO_PRINT("Before MoveLoop"); + MoveLoop(); + //MONO_PRINT("After MoveLoop"); + //MONO_PRINT("Before DrawScreen"); + drawscreen(Player + screenpeek); + //MONO_PRINT("After DrawScreen"); + + if (QuitFlag) + break; + + if (ExitLevel) + { + ExitLevel = FALSE; + break; + } + } + + ready2send = 0; +} + +void swexit(int exitval) +{ + exit(exitval); +} + +VOID DosScreen(VOID) +{ +#if 0 +#ifdef SW_SHAREWARE +#define DOS_SCREEN_NAME "SHADSW.BIN" +#else +#define DOS_SCREEN_NAME "SWREG.BIN" +#endif + +#define DOS_SCREEN_SIZE (4000-(80*2)) +#define DOS_SCREEN_PTR ((void *)(0xB8000)) + int fin; + int i; + char buffer[DOS_SCREEN_SIZE]; + + fin = kopen4load(DOS_SCREEN_NAME,0); + if (fin == -1) + return; + + kread(fin, buffer, sizeof(buffer)); + memcpy(DOS_SCREEN_PTR, buffer, DOS_SCREEN_SIZE); + kclose(fin); + move_cursor(23,0); + _displaycursor(_GCURSORON); +#endif +} + +#if 0 //PLOCK_VERSION +VOID AlphaMessage(VOID) +{ + Global_PLock = TRUE; // Set the hardwired parental lock mode! + buildputs("" + " SHADOW WARRIOR(tm) Version 1.2 \n" + "Copyright (c) 1997 3D Realms Entertainment\n" + "\n\n" + " NOTE: This version of Shadow Warrior has been modified from it's\n" + " original form. All of the violent and mature content has been\n" + " removed. To download a patch to restore this version to its\n" + " original form visit www.3drealms.com, www.gtinteractive.com, or look\n" + " inside your retail packaging for information about this version.\n\n\n" + ); +} +#endif + +#if 0 //UK_VERSION +VOID AlphaMessage(VOID) +{ + buildputs("" + " SHADOW WARRIOR(tm) Version 1.2 (UK Version) \n" + "Copyright (c) 1997 3D Realms Entertainment\n" + "\n\n" + " NOTE: This is a modified version of Shadow Warrior created for the UK.\n" + " It has been altered from its original version to replace \"shurikens\" \n" + " with darts. We apologize for the inconvenience and hope you enjoy the\n" + " game. Visit us on the web at www.3drealms.com.\n\n\n" + ); +} +#endif + +#if 1 //!UK_VERSION && !PLOCK_VERSION +VOID AlphaMessage(VOID) +{ + if (SW_SHAREWARE) + { + buildputs("SHADOW WARRIOR(tm) Version 1.2 (Shareware Version)\n"); + } + else + { + buildputs("SHADOW WARRIOR(tm) Version 1.2\n"); + } + buildputs("Copyright (c) 1997 3D Realms Entertainment\n\n\n"); +} +#endif + +typedef struct +{ + char notshareware; + char *arg_switch; + short arg_match_len; + char *arg_fmt; + char *arg_descr; +} CLI_ARG; + +#if DEBUG +CLI_ARG cli_dbg_arg[] = +{ + {0, "/demosyncrecord", 13, "-demosyncrecord", "Demo sync record" }, + {0, "/demosynctest", 13, "-demosynctest", "Demo sync test" }, + {0, "/cam", 4, "-cam", "Camera test mode" }, + {0, "/debugactor", 11, "-debugactor", "No Actors" }, + {0, "/debuganim", 10, "-debuganim", "No Anims" }, + {0, "/debugso", 8, "-debugso", "No Sector Objects" }, + {0, "/debugsector", 12, "-debugsector", "No Sector Movement" }, + {0, "/debugpanel", 11, "-debugpanel", "No Panel" }, + {0, "/mono", 5, "-mono", "Mono" }, +}; +#endif + + +CLI_ARG cli_arg[] = +{ + {0, "/?", 2, "-?", "This help message" }, +//#ifndef SW_SHAREWARE +//{"/l", 2, "-l#", "Level (1-11)" }, +//{"/v", 2, "-v#", "Volume (1-3)" }, + {1, "/map", 4, "-map [mapname]", "Load a map" }, + {1, "/nocdaudio", 5, "-nocd